On Sun, 17 Mar 2002, Lev Assinovsky wrote:
> Date: Sun, 17 Mar 2002 20:39:12 +0300
> From: Lev Assinovsky <[EMAIL PROTECTED]>
> Reply-To: Jakarta Commons Developers List <[EMAIL PROTECTED]>
> To: Jakarta Commons Developers List <[EMAIL PROTECTED]>
> Subject: Re: [dbcp] Works with JNDI, but some remarks...
>
> Hi Jason!
> My servlet dbcpPoolStartup successfully creates Pool instance.
> It's loaded on startup and defined in $CATALINA_HOME/conf/web.xml
> At this level I have the troubles with binding pool instance
> to arbitrary name (JNDI I guess). I get "Context is read only".
> (BTW, the init method of my servlet is called 5 times (?!))
> What am I doing wrong?
> Thanks,
> Lev
>
That's two separate issues.
First, the JNDI namespace that Tomcat 4 gives you is indeed read only --
it is populated from resources that are configured in server.xml, as
described in the Tomcat documentation. In Tomcat 4.0.x, the default
connection pool is Tyrex, but you can use the one from DBCP by declaring
your own "factory" (again, as described in the JNDI HOW-TO docs) class of
"org.apache.commons.dbcp.BasicDataSourceFactory".
Second, your servlet probably implements the SingleThreadModel interface,
so Tomcat does what the servlet spec suggests and creates a pool of
instances (initializing each of them) at startup time. If you don't want
this, one answer is to not implement SingleThreadModel (avoiding
SingleThreadModel is a good idea anyway), but you should also really look
at doing one-time application initialization in a ServletContextListener
that was introduced in Servlet 2.3 (and therefore supported in Tomcat 4).
Basically, you do the following:
* Create a class that implements javax.servlet.ServletContextListener
* Register it with an element in your web.xml file:
<listener>
<listener-class>com.mycompany.mypackage.MyListener</listener-class>
</listener>
* In the contextInitialized() method, do whatever setup
you need. Typically, you will create objects and store
them as servlet context attributes. This method is
guaranteed to be called exactly once, before any requests
are processed by your application.
* In the contextDestroyed() method, you can do any cleanup
needed at shutdown time. This method is guaranteed to be
called exactly once, after the last request has been processed.
More info on the servlet related concepts can be found in the Servlet 2.3
Specification <http://java.sun.com/products/servlet/download.html>, and
you'll get lots more help on general servlet issues on the TOMCAT-USER
mailing list.
Craig McClanahan
> Jason R Lee wrote:
> >
> > Well,
> >
> > Here's some sample code for a servlet registration in web.xml:
> >
> > registers the servlet:
> >
> > <servlet>
> > <servlet-name>dbcpPoolStartup</servlet-name>
> > <servlet-class>org.some.servlet.package</servlet-class>
> > <init-param>
> > <param-name>datasourceURI</param-name>
> > <param-value>jdbc:oracle:thin:user/password:1521:sid</param-value>
> > </init-param>
> > <load-on-startup>1</load-on-startup>
> > </servlet>
> >
> > provides the url mapping:
> >
> > <servlet-mapping>
> > <servlet-name>dbcpPoolStartup</servlet-name>
> > <url-pattern>/dbcpPoolStartup</url-pattern>
> > </sevlet-mapping>
> >
> > We'll get more to the servlet specifics in a bit.
> >
> > there's 2 web.xml files you could put it in, both of which will have different
>affects.
> >
> > If you In your $TOMCAT_HOME/conf/web.xml, then this will load when the Tomcat
>container starts. If you have multiple webapps that happen to use the same db
>connection, database, etc., then this would be beneficial. However, if you do have
>multiple webapps using a database, then they prob have separate tables, so the above
>probably wouldn't work to well. However, you could make a servlet that accepted
>multiple parameters for different datasourceURI's.
> >
> > example:
> >
> > <init-param>
> > <param-name>shoppingDatasourceURI</param-name>
> > <param-value>jdbc:oracle:thin:shopuser/password:1521:sid</param-value>
> > </init-param>
> > <init-param>
> > <param-name>portalDatasourceURI</param-name>
> > <param-value>jdbc:oracle:thin:portaluser/password:1521:sid</param-value>
> > </init-param>
> > <init-param>
> > <param-name>emailDatasourceURI</param-name>
> > <param-value>jdbc:oracle:thin:emailuser/password:1521:sid</param-value>
> > </init-param>
> >
> > Right? So on init, the 3 names and values would be passed in and, if you built
>your sevlet to deal with that, it could set up 3 different pools for the different
>webapps running. This would probably only be the case, tho, if you were to put this
>at the container startup level, which is important to understand.
> >
> > The other web.xml lives in $TOMCAT_HOME/webapps/yourwebapp/WEB-INF. The first
>example (the single init value) would work fine at this level. You init one pool for
>your entire webapp, which is usually the case. The servlet then would be responsible
>for setting up the connection and JNDI info and then scoping it to the appplication
>level.
> >
> > It gets really cool with this stuff because you can basically then build in other
>methods into your servlet that could allow it to dynamically switch, at run-time
>(altho, that has to be thought out since you would be changing pools and such and
>your app might not be too happy about that) allowing you to 'fix', possibly, or
>change various potential problems that might crop up. Or switch user names, whatever.
>Point is is that a servlet can make a very nice admin tool for
>starting/stopping/reloading pool instances as well as anyt other app scoped objects.
> >
> > One thing to keep in mind, every time the webapp is started there might be a
>little lag time associated with the pool and JNDI setup. There's all kinds of tricks
>you can use to get around that (i.e. you *could* ;) have a servlet that started at
>the Tomcat init level that then went out and init'd your sevlets, but that's another
>topic in iteself).
> >
> > I'm pretty sure this is correct and i remembered everything, but if not, someone
>feel free to correct me. So hopefully this helps or provides a little insight.
> >
> > cheers,
> >
> > - jason
> >
> > -----Original Message-----
> > From: Lev Assinovsky [mailto:[EMAIL PROTECTED]]
> > Sent: Thu 3/14/2002 6:54 AM
> > To: Jakarta Commons Developers List
> > Cc:
> > Subject: Re: [dbcp] Works with JNDI, but some remarks...
> > Jason,
> > it's pretty interesting what you are saying. I thought about such
> > approach but
> > I don't have enough knowledge in Tomcat.
> > Let me few stupid questions please:
> > 1. I can write servlet which will do pool creation and JNDI
> > registration. But how to set it up to start it upon init of the
> > container?
> > 2. How to setup servlet upon init of Tomcat?
> >
> > Thanks in advance!
> >
> > Jason R Lee wrote:
> > >
> > > All users will definitely be application scope. To further that, it would
>probably be best to have a servlet, upon init of the container, start the connection
>pool and then register it via JNDI. Then your bean would be accessing that instead of
>creating it every time they are needed. The whole point behind connection pooling is
>for giving multiple objects, usually, over the scope of the application access to
>preconneted pools (sorry if this is review). Creating a new pool obj based on a
>request level scope pretty much defeats the purpose.
> > >
> > > I'm actually working on dbcp at this level now. I just have a servlet start the
>pool when tomcat starts up. Pretty easy stuff. I'm interested in seeing how well the
>pool works vs. just getting a regular connection every time (I'm sure dbcp will smoke
>it).
> > >
> > > cheers,
> > >
> > > - Jason
> > >
> > > -----Original Message-----
> > > From: Lev Assinovsky [mailto:[EMAIL PROTECTED]]
> > > Sent: Thu 3/14/2002 5:23 AM
> > > To: Jakarta Commons Developers List
> > > Cc:
> > > Subject: [dbcp] Works with JNDI, but some remarks...
> > > Hello all!
> > > I got dbcp working through JNDI in Tomcat 4.0.4b1.
> > > Thank you! (I got tired of Tyrex :-))
> > >
> > > But I have several issues.
> > >
> > > My configuration server.xml is:
> > > <Resource name="lev/DataSource" auth="Container"
> > > type="javax.sql.DataSource"/>
> > > <ResourceParams name="lev/DataSource">
> > > <parameter><name>factory</name>
> > >
> > > <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
> > > </parameter>
> > >
> > >
> > > <parameter><name>username</name><value>wv</value></parameter>
> > >
> > > <parameter><name>password</name><value>wv</value></parameter>
> > >
> > > <parameter><name>maxActive</name><value>100</value></parameter>
> > >
> > > <parameter><name>maxIdle</name><value>30000</value></parameter>
> > >
> > > <parameter><name>maxWait</name><value>100</value></parameter>
> > > <parameter><name>driverClassName</name>
> > > <value>org.gjt.mm.mysql.Driver</value></parameter>
> > > <parameter><name>url</name>
> > >
> > > <value>jdbc:mysql://localhost:3306/WV?user=wv&password=wv</value></parameter>
> > > </ResourceParams>
> > >
> > > 1. When I had 'user' instead of 'username' (Tyrex allows both) I got
> > > NullPointer exception
> > > in connectionProperties.put("user", username) in BasicDataSource.
> > >
> > > 2. When I didn't have maxActive I got infinite loop in borrowObject()
> > > in GenericObjectPool.
> > >
> > > Actually I don't have clear understanding of the pool's parameters.
> > > I'all really appreciate
> > > if somebody could make it clear for me.
> > >
> > > Also with xml parameters above I got very often:
> > >
> > > java.sql.SQLException: Communication link failure: java.io.IOException
> > > at org.gjt.mm.mysql.MysqlIO.clearAllReceive(Unknown Source)
> > > at org.gjt.mm.mysql.MysqlIO.sqlQueryDirect(Unknown Source)
> > > at org.gjt.mm.mysql.MysqlIO.sqlQuery(Unknown Source)
> > > at org.gjt.mm.mysql.Connection.execSQL(Unknown Source)
> > >
> > > or
> > > NullPointerException.
> > >
> > > However I created new connection pool (through JNDI lookup) on every
> > > HTTP request since my bean where I did all above
> > > had a scope="request" (just for testing).
> > >
> > > And the last GLOBAL question. If I get datasource and connection in the
> > > bean, then
> > > the only way to have one connection pool for all users who sends HTTP
> > > request to my JSP (which using my bean)
> > > is to have the scope "application" for the bean. Am I right?
> > >
> > > Sincerely,
> > > --
> > > Lev Assinovsky Peterlink Web
> > > Programmer St. Petersburg, Russia
> > > Tel/Fax: +7 812 3275343 197022 ul.Chapigina 7?
> > > E-mail: [EMAIL PROTECTED]
> > >
> > > --
> > > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
> > > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
> > >
> > > ------------------------------------------------------------------------
> > > Name: winmail.dat
> > > winmail.dat Type: application/ms-tnef
> > > Encoding: base64
> > >
> > > ------------------------------------------------------------------------
> > > --
> > > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
> > > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
> >
> > --
> > Lev Assinovsky Peterlink Web
> > Programmer St. Petersburg, Russia
> > Tel/Fax: +7 812 3275343 197022 ul.Chapigina 7?
> > E-mail: [EMAIL PROTECTED]
> >
> > --
> > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
> >
> > ------------------------------------------------------------------------
> > Name: winmail.dat
> > winmail.dat Type: application/ms-tnef
> > Encoding: base64
> >
> > ------------------------------------------------------------------------
> > --
> > To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
>
> --
> Lev Assinovsky Peterlink Web
> Programmer St. Petersburg, Russia
> Tel/Fax: +7 812 3275343 197022 ul.Chapigina 7�
> E-mail: [EMAIL PROTECTED]
>
> --
> To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
>
>
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>