Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Servlet context for non-servlet bean

Status
Not open for further replies.

flowcontrol

Programmer
Oct 16, 2002
86
0
0
US
I have a database that uses sequentially numbered primary keys (ID). I developed a bean to hold the next ID for each of several tables. Each servlet that needs to insert a record into a table gets the ID for the record from the bean. The bean is instantiated from within a JSP page (<jsp:useBean ... scope="application"/>).

The bean's properties (the next IDs for several tables) are initialized in the constructor by querying the database. I've got it working perfectly using a hard-coded database driver and connection string. Now, I want to change it to get the database driver and connection string from context-params defined in the deployment descriptor.

The problem I'm having is that I can't figure out how to get the servlet context (from which I can get the context-param). The bean is not a servlet, so it does not have access to a ServletRequest object (from which I could get the context).

How can this bean get a reference to the ServletContext?
 
Pass it into the bean's constructor or method (as long as you are running your app in a servlet container).

BTW, I would use connection pooling for your JDBC access - it will speed up your app no end, and make it a lot more controllable ...



--------------------------------------------------
Free Database Connection Pooling Software
 
Pass the ServletContext to the bean? How do I do that. I'm instantiating the bean from within a JSP page like this:

<jsp:useBean id="top" class="com.company.dept.TopIdBean" scope="application"/>
 
You can use scriptlet tags instead of jsp tags :

<%
com.company.dept.TopIdBean bean = new com.company.dept.TopIdBean(request.getServletContext());
%>

Or write your own custom tag which wraps the bean, at which point you have access to the PageContext object ...

--------------------------------------------------
Free Database Connection Pooling Software
 
I haven't tried wrapping the bean in a custom tag yet, but the scriptlet isn't working.

The compiler "can't resolve symbol" 'request'. That should be a HttpServletRequest object, right? Did you mean for me to type that literally? I don't know how to get the HttpServletRequest object, or the pageContext while inside the scriptlet.
 
What servlet container are you using ? The "request" object is standard, and is present in all JSP pages I've ever written (using Tomcat 3 to 5).

--------------------------------------------------
Free Database Connection Pooling Software
 
I'm using Tomcat 5. I've tried to refer to the request object (and it's servlet context property) in these ways:

request.getServletContext()
pageContext.request.getServletContext()

but neither one worked.
 
Look in $TOMCAT_HOME/work/Catalina/localhost/yourWebAppName/org/apache/jsp

and open the JSP_NAME.java file . This is the jsp file compiled into what is basically a servlet.

You will see something like this :

Code:
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class home_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static java.util.Vector _jspx_dependants;

  static {
    _jspx_dependants = new java.util.Vector(2);
    _jspx_dependants.add("/header.inc");
    _jspx_dependants.add("/footer.inc");
  }

  public java.util.List getDependants() {
    return _jspx_dependants;
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

In the _service() method, you will see that the PageContext, HttpSession, HttpServletRequest (var name request), HttpServletResponse and ServletContext(var name application) are all set up for you ... so you can use them like you would any other variable ... ie :

<%
com.company.dept.TopIdBean bean = new com.company.dept.TopIdBean(request.getServletContext());
%>


or

<%
com.company.dept.TopIdBean bean = new com.company.dept.TopIdBean(application);
%>




--------------------------------------------------
Free Database Connection Pooling Software
 
Not on topic I know but, I am trying to post a new thread and can't seem to get the page. Is anyone else having this problem or is it just me? Sorry guys.
 
Assuming you have a context parameter defined as:
Code:
    <context-param>
        <param-name>foo</param-name>
        <param-value>bar</param-value>
    </context-param>
And assuming you have a simple class like:
Code:
package beans;
public class TestBean {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
Then your JSP can access this like:
Code:
<%@ page import="beans.*" %>
<% String value = application.getInitParameter("foo"); %>
<jsp:useBean id="test" class="beans.TestBean"/>
<jsp:setProperty name="test" property="name" value="<%= value %>"/>
Value is <jsp:getProperty name="test" property="name"/>
The application variable is the ServletContext. Cheers, Neil
 
Thank you for hanging in there with me. I reviewed the generated java file, and indeed, the _jspService method has request and response arguments just like HttpServlet. I can see my scriptlet in there, referencing the request object, but it is not working. I'm getting this error when I try to fetch the jsp page:
Code:
... index_jsp.java:89: cannot resolve symbol
...
com.company.dept.TopIdBean top = new com.company.dept.TopIdBean(request.getServletContext());
                                  ^
Any thoughts?
 
Have you done :

<%@ page import="com.company.dept.*" %>



--------------------------------------------------
Free Database Connection Pooling Software
 
sedj:

Yes, I've imported my package, but it's not necessary because I'm using the fully quallified class name (I tried it both ways just to make sure). The error is that the compiler can't resolve the symbol "request". I'm stumped. It looks like it should work; I mean, 'request' has to be defined because it's a parameter to the method! (and it's spelled correctly).

toolkit:

Thanks for your input. I could use that approach by writing a setContext() and a setInit(), the latter doing the database query and initializing the other properties.
 
Alternatively, if you intend all instances of your beans to share initialisation strings, then you can have:
Code:
public class MyBean {
    private static String initValue;
    public static void setInitValue(String value) {
        initValue = value;
    }
}
Then, create and register a ServletContextListener class, to initialise this value as soon as the application goes live:
Code:
public class SCL implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce)
    {
        ServletContext app = sce.getServletContext();
        MyBean.setInitValue(app.getInitParameter("foo"));
    }
    public void contextDestroyed(ServletContextEvent sce)
    {
    }
}
This frees your JSP from having to rememeber to set these initialisation parameters.
Cheers, Neil
 
I don't think the error is about the "request" ... the Tomcat javac error output is always poor. I expect then that the error is that TopIdBean does not have a constructor that allows a ServletContext. You can test this by having just the following a jsp page :

Code:
<%@ page import="com.company.dept.*" %>
<%
TopIdBean bean = null;
out.println("Request object : " +request);
%>

If this displays OK, then its the constructor.

--------------------------------------------------
Free Database Connection Pooling Software
 
You're right. request.toString() prints OK.

You're right about the constructor. I had a one-arg constructor, but I had commented-out my default constructor. Beans must have a no-arg counstructor, right? Here is what I have now:
Code:
public TopIdBean() {
  super();
}

public TopIdBean(ServletContext context) {
  this();
  // the rest of my initialization code goes here
}
However, I am still getting the same error. What's wrong with my constructors?
 
No idea.

Try it another way - leave your noarg constructor & have a method to set the context :

public void SetContext(ServletContext context) {
this.context = context;
}

and set this in your JSP. Don;t forget to import the ServletContext in the bean.

--------------------------------------------------
Free Database Connection Pooling Software
 
Taking your idea of writing a setter method for setting the context, I also would have to move the initialization out of the constructor (because it doesn't have all the data it needs at that point. I would go back to having only the default constructor and would create setContext() and setInit() methods. Then I could use <jsp:setProperty ...> to set the context and invoke the setInit method.

I say "could" and "would" because, while all this discussion was going on, I discover the ServletContextListener interface (coincidentally, toolkit was suggesting it at about the same time). I wrote a very simple Listener to instantiate and initialize the bean, and to put it in the application scope. This seems like a good solution as it avoids putting scriplets in my JSP page, and the Listener is expandable to do other "global resource" stuff.
Code:
package com.company.dept;

import javax.servlet.*;
import com.company.dept.TopIdBean;

public class MyListener implements ServletContextListener {

  public void contextInitialized(ServletContextEvent sce) {
        ServletContext application  = sce.getServletContext();

    String dbDriver = application.getInitParameter("database.driver");
    String connectionUrl = application.getInitParameter("connection.url");

    TopIdBean top = new TopIdBean();
    top.setDbDriverName(dbDriver);
    top.setDbConnectUrl(connectionUrl);
    top.init();
    application.setAttribute("top", top);
  }

  public void contextDestroyed(ServletContextEvent sce) {
    ServletContext application  = sce.getServletContext();
    application.removeAttribute("top");
  }
}
So, although I haven't figured out why the JSP page won't compile, I have to abandon that effort as it's now only academic. Maybe one of these days ...

Thank you all for ALL of your comments and suggestions. I really do appreciate it.
 
That does sound like a better solution for your problem. Glad you got it sorted out !

--------------------------------------------------
Free Database Connection Pooling Software
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top