4

I have a webservice with Java Servlets on a Tomcat server. In my Servlet I use a database pool like this:

envContext = new InitialContext();
DataSource ds = (DataSource) envContext.lookup( "java:/comp/env/jdbc/Database" );
con = ds.getConnection();

For initialisation I have this in my web.xml:

<resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/Database</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>

Then there is the context.xml which seems to be the important step here:

<?xml version="1.0" encoding="UTF-8"?>
 <!-- The contents of this file will be loaded for each web application -->
  <Context crossContext="true">

    <!-- Default set of monitored resources -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>

   <Resource name="jdbc/Database" auth="Container"
        type="javax.sql.DataSource"
        maxActive="100" maxIdle="30" maxWait="10000"
        username="user" 
        password="password" 
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/configerror_db"/>
</Context>

I read many other questions conserning this error, but I couldn't solve it.

First I want to explain, that I don't get this error when using my linux-machine. Hence I installed the same code in Eclipse on my Windows machine I get this context-environment error.

Other Answers say to do this.

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, 
    "<initialContextFactory>");
env.put(Context.PROVIDER_URL, "<url>");
env.put(Context.SECURITY_PRINCIPAL, "<user>");
env.put(Context.SECURITY_CREDENTIALS, "<password>");
ctx = new InitialContext(env);

But I don't know what the initialContextFactory is AND shouldn't the context.xml do exactly this? As I said on linux it works.

Can someone help me out here? What am I missing? I don't want to write the user and password in every file where I use a database connection. I thought hell yeah this is awesome. The credentials are just in the context.xml, but now on windows it is not working.

Thanks for any advice.

Community
  • 1
  • 1
progNewbie
  • 4,362
  • 9
  • 48
  • 107
  • 1
    Exception strongly suggests that JNDI is disabled on Tomcat instance in question. No way that you can enable this from webapp side on. All you can do at this point is to contact the responsible server admin for details (ask why it is disabled and what their proposed alternatives are). Proposed code snippet as possible solution is by the way only applicable on Java SE applications, not on Java EE applicions as it's the server itself who's responsible for that, not the deployed webapp (nor can it be). – BalusC May 30 '16 at 10:05
  • 1
    This code won't work unless you're running in a Tomcat container. Is that the case on both machines? – user207421 May 30 '16 at 10:27
  • @EJP: I am very new to JAva Servlets and Tomcat. I am just using Eclipse to run my code and the tomcat Server. I do this on both machines. – progNewbie May 30 '16 at 11:49

3 Answers3

3

Hi progNewbie,

I am working on Windows OS and Eclipse IDE as specially on same type of project for which are you looking.

you need to update your code at following places(3-Changes)...

1. Do Following Java Changes,

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
......
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/Database");
conn = ds.getConnection();

2. Configure Java Web-Application's web.xml likewise,

......
  <resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/Database</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>
......... 

3. Into Tomcat's server.xml file do following changes :

..................
<!-- Assume my application runs on localhost... -->
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">

<Valve className=..../>

<Context docBase="...." path="..." reloadable="true" source=".....">

<!-- Assume i am using Oracle Database so that driverClass(below) Attribute's Value will be oracle.jdbc.driver.OracleDriver -->
<Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" 
    maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/Database" password="db-password" 
    type="javax.sql.DataSource" url="db-connection-url" username="db-user-name" 
/>

</Context>

</Host>
............

EDITED :

enter image description here

Let me know if still stuck up then.

Vishal Gajera
  • 4,137
  • 5
  • 28
  • 55
-1

Your configuration in web.xml and context.xml is OK. There is no need to reproduce it by code filling a HashTable and so.

I have tested similar experiments successfully. The problem might be as simple as there is an slash too much in your JNDI url: Try this:

DataSource ds = (DataSource) envContext.lookup( "java:comp/env/jdbc/Database" ); 
Little Santi
  • 8,563
  • 2
  • 18
  • 46
-1

UPDATE:

What is initialContextFactory and what it does?

Initial context factory

The constant that holds the name of the environment property for specifying the initial context factory to use. The value of the property should be the fully qualified class name of the factory class that will create an initial context. This property may be specified in the environment parameter passed to the initial context constructor, an applet parameter, a system property, or an application resource file.

If it is not specified in any of these sources, NoInitialContextException is thrown when an initial context is required to complete an operation.

The value of this constant is "java.naming.factory.initial".

For more details: you can follow this tutorial.


Server Admin Working Area:

When server admin creates a data source, he associates it with a Java Database Connectivity (JDBC) provider that is configured for access to a specific vendor database. The application server requires both objects for your applications to make calls to that particular database and receive data from it. The data source provides connection management capabilities that physically make possible these exchanges between your applications and the database.

The server has to be restarted for the newly-created datasource to be available for a Java Naming and Directory Interface (JNDI) from the application.

In server configuration, there is a option named jndi name. Server admin gives input Java Naming and Directory Interface (JNDI) name in the JNDI name field. The application server uses the JNDI name to bind resource references for an application to this data source.

Caution:

  1. Do not assign duplicate JNDI names across different resource types, such as data sources versus J2C connection factories or JMS connection factories.
  2. Do not assign duplicate JNDI names for multiple resources of the same type in the same scope.

Resource Link:

Configuring a data source using the administrative console


Developer working area:

There three steps to configure and run JNDI Datasource Connection pool for any Java Web application:

  • Configure data source in Server and create JNDI name.
  • Configure web.xml
  • Configure your bean with JNDI Datasource
  • Include JDBC driver library on Server lib

Database wise configuration and code is given here.

Resource Link:

  1. JNDI Resources HOW-TO in Apche Tomcat 7
  2. How to configure MySQL DataSource in Tomcat 6


As Mr. @BalusC said that,

Exception strongly suggests that JNDI is disabled on Tomcat instance.

So for enabling JNDI, you can get many tutorials.

A more detailed explanation of what is going on in enabling JNDI, complete with an example, can be found here.

For more you can go through this tutorial also.

Resource Link:

  1. Tomcat DataSource JNDI Example
Community
  • 1
  • 1
SkyWalker
  • 28,384
  • 14
  • 74
  • 132
  • 1
    Those links doesn't show how to **enable** JNDI in Tomcat. Those links only show how to **use** JNDI in a webapp deployed to Tomcat. Moreover, you should include the real answer in the post, not "hide" it behind a link. Right now it looks too much like "blind guessing". An answer should be able to stand at its own and still answer the concrete question without the need to click any links in it. – BalusC Jun 01 '16 at 11:56