Announcement Announcement Module
Collapse
No announcement yet.
JNDI Lookup Problems on Tomcat 5.5.9 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JNDI Lookup Problems on Tomcat 5.5.9

    Hello,

    I am using Spring 1.2 with Hibernate 3.0.5. My production environment is WebLogic 8.1 SP 5, but for development I'd like to use Tomcat 5.5.9 because it's so much faster to load than WebLogic.

    I'm having trouble with the JNDI lookup when deploying the application to Tomcat. I've scoured the web and it looks like I'm not the only one to have this problem, but I haven't been able to find a fix that works. I'll include a lot of info here in the hopes that somebody can give me a hand. The deployment works in WebLogic, so I know I'm close.

    ============================================
    Here's how I've defined the transaction beans in applicationContext.xml:
    ============================================


    <bean id="springJtaTransactionManager"
    class="org.springframework.jdbc.datasource.DataSou rceTransactionManager" />

    <!-- transaction manager -->
    <bean id="jtaTransactionInterceptor"
    class="org.springframework.transaction.interceptor .TransactionInterceptor">
    <property name="transactionManager">
    <ref local="springJtaTransactionManager" />
    </property>

    <property name="transactionAttributes">
    <props>
    <prop key="search*">PROPAGATION_REQUIRED,readOnly,-com.biperf.core.exception.ServiceErrorExceptionWit hRollback,timeout_3000</prop>
    <prop key="is*">PROPAGATION_REQUIRED,readOnly,-com.biperf.core.exception.ServiceErrorExceptionWit hRollback,timeout_3000</prop>
    <prop key="get*">PROPAGATION_REQUIRED,readOnly,-com.biperf.core.exception.ServiceErrorExceptionWit hRollback,timeout_3000</prop>
    <prop key="report*">PROPAGATION_REQUIRED,-com.biperf.core.exception.ServiceErrorExceptionWit hRollback,timeout_10000</prop>
    <prop key="insertPromotionEligibilityCriteriaAudienceRec ords*">PROPAGATION_REQUIRED,-com.biperf.core.exception.ServiceErrorExceptionWit hRollback,timeout_10000</prop>
    <prop key="*">PROPAGATION_REQUIRED,-com.biperf.core.exception.ServiceErrorExceptionWit hRollback,timeout_3000</prop>
    </props>
    </property>
    </bean>


    ============================================
    Here's how I have defined the datasource lookup. Notice that I'm using the JndiFactoryObjectBean:
    ============================================
    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryB ean">
    <property name="jndiName"><value>jdbc/datasource-travelsystem</value></property>
    </bean>



    You can see that the JNDI name is jdbc/datasource-travelsystem. Remember that this works in WebLogic.

    ============================================
    This is the code I have in the WAR file's META-INF/context.xml file that should set up the datasource in Tomcat. I've verified that it exists in Tomcat:
    ============================================
    <Context path="/tosched">
    <Resource name="jdbc/datasource-travelsystem" auth="Container"
    type="javax.sql.DataSource" username="bitravel" password="l3v9rt1b"
    driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@localhost:1521:travel"
    maxActive="8" maxIdle="4"/>

    I know that the datasource is available because if I use this code in a test servlet:

    Context initContext = new InitialContext();
    Context envContext = (Context)initContext.lookup("java:/comp/env");
    DataSource ds = (DataSource)envContext.lookup("jdbc/datasource-travelsystem");
    Connection conn = ds.getConnection();


    It doesn't fail.


    When I deploy the app to Tomcat 5.5.9, it fails with this error:

    org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'dataSource' defined in class path resource [datasourceContext-server.xml]: Initialization of bean failed; nested exception is javax.naming.NameNotFoundException: Name jdbc is not bound in this Context


    With a stack trace of (abbreviated):

    javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
    at org.apache.naming.NamingContext.lookup(NamingConte xt.java:769)
    at org.apache.naming.NamingContext.lookup(NamingConte xt.java:152)
    at org.apache.naming.SelectorContext.lookup(SelectorC ontext.java:136)
    at javax.naming.InitialContext.lookup(InitialContext. java:351)
    at org.springframework.jndi.JndiTemplate$1.doInContex t(JndiTemplate.java:123)
    at org.springframework.jndi.JndiTemplate.execute(Jndi Template.java:85)
    at org.springframework.jndi.JndiTemplate.lookup(JndiT emplate.java:121)
    at org.springframework.jndi.JndiLocatorSupport.lookup (JndiLocatorSupport.java:71)
    at org.springframework.jndi.JndiObjectLocator.lookup( JndiObjectLocator.java:85)
    at org.springframework.jndi.JndiObjectFactoryBean.aft erPropertiesSet(JndiObjectFactoryBean.java:124)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.invokeInitMethods(Abstr actAutowireCapableBeanFactory.java:937)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:334)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:222)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:146)
    at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:271)
    at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:310)
    at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:80)
    at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:65)
    at com.biperf.core.utils.ApplicationContextFactory.ge tApplicationContext(ApplicationContextFactory.java :113)



    Now, some suggestions on the web have said to include java:comp/env/ somewhere, which I've tried in various places but to no avail. The error message may change, but it still doesn't work.

    I've got to believe that somebody has Spring working this way on Tomcat. Can anybody give me some guidance? Since it works on WebLogic I know it's close, I just can't figure out what I need to tweak for Tomcat.

    Thank you very much!!!!

    Ryan Asleson
    Co-Author, "Foundations of Ajax" and "Pro Ajax and Java Frameworks"
    Lead Developer, Taconite (http://taconite.sf.net/)

  • #2
    Ryan,

    The format of the jndiName value is different for Tomcat - instead of 'jdbc/datasource-travelsystem', you need to use 'java:comp/env/jdbc/datasource-travelsystem'

    As you development environment (Tomcat) differs from your production environment (Weblogic), you'll have to externalise that part of the configuration.

    See this thread for more information...

    http://forum.springframework.org/showthread.php?t=27956

    Bob

    Comment


    • #3
      Thanks, Bob, for the reply.

      I change my setup to be this:

      <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryB ean">
      <property name="jndiName"><value>java:comp/env/jdbc/datasource-travelsystem</value></property>
      </bean>


      But now this is the error it's throwing:

      org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'springJtaTransactionManager' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: dataSource is required
      java.lang.IllegalArgumentException: dataSource is required
      at org.springframework.jdbc.datasource.DataSourceTran sactionManager.afterPropertiesSet(DataSourceTransa ctionManager.java:141)
      at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.invokeInitMethods(Abstr actAutowireCapableBeanFactory.java:937)
      at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:334)
      at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:222)
      at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:146)
      at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:277)
      at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:310)
      at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:80)
      at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:65)
      at com.biperf.core.utils.ApplicationContextFactory.ge tApplicationContext(ApplicationContextFactory.java :113)


      So the error message has changed but it's still complaining about something. Any idea why or how I should debug this??

      Thank you very much!!!!

      -Ryan

      Comment


      • #4
        Ryan,

        The only difference, in structure, that I can see between your config and mine, is that you've not specified the datasource wiring explicitly on your 'springJtaTransactionManager' bean - maybe the autowiring isn't working for some reason. I've not used autowiring myself, as I like to state things explicitly.

        Give this a try...
        Code:
        <bean id="springJtaTransactionManager"
        class="org.springframework.jdbc.datasource.DataSou rceTransactionManager" >
            <property name="dataSource">
                <ref bean="dataSource"/>
            </property>
        </bean>

        Comment


        • #5
          Just looked at the docs and discovered that autowiring is off by default - did you enable it specifically?

          Set this for the entire context file by changing you <beans> element like this...

          Code:
          <bean default-autowire="byName">
          or for an individual bean...

          Code:
          <bean id="springJtaTransactionManager" autowire="byName"
          class="org.springframework.jdbc.datasource.DataSou rceTransactionManager" />
          Fingers crossed!

          Comment


          • #6
            Bob, that seems to have helped. I'm running into other problems now but I think the data source is being picked up in Tomcat. Thank you so much. I'll be sure to ask if I need more help.

            -Ryan

            Comment


            • #7
              OK, everything is working great now. Bob, thanks for all of your help, I would have been in trouble without your help.

              For the record, let me fill you in on what the whole story was, in case it ever comes up again. As I stated earlier my production envrironment is Weblogic 8.1 SP 5. Because of this the transaction manager used the Weblogic-specific transaction manager in the production environment:

              Code:
              <bean id="springJtaTransactionManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager" >
              </bean>

              Note that there is no dataSource property wiring here. The Weblogic transaction manager must automatically pick up the data source somehow.

              When working in the Tomcat 5.5.9 environment, I used the basic transaction manager, which requires that the data source be wired explicitly:

              Code:
                  <bean id="springJtaTransactionManager"
                      class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
                      <property name="dataSource">
                          <ref bean="dataSource"/>
                      </property>
                  </bean>
              I use Ant to dynamically set this all up correctly during the build process.

              For the record, Tomcat requires that the datasource have "java:comp/env/" appended to its name:

              Code:
                  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                      <property name="jndiName"><value>java:comp/env/jdbc/datasource-travelsystem</value></property> 
                  </bean>
              While Weblogic doesn't need it:


              Code:
                  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                      <property name="jndiName"><value>jdbc/datasource-travelsystem</value></property> 
                  </bean>

              And the data source for Tomcat is set up in the WAR file's META-INF/context.xml file:

              Code:
                  <Resource name="jdbc/datasource-travelsystem" auth="Container"
                  type="javax.sql.DataSource" username="zz1" password="vcre3"
                  driverClassName="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@localhost:1521:travel"
                  maxActive="8" maxIdle="4"/>
              Thanks again for the help, and maybe this will help somebody else in the future.

              -Ryan

              Comment


              • #8
                Ryan,

                Can't comment on Weblogic 'automatically picking up the datasource' - despite one of my previous projects using Weblogic as its production environment, that was deemed 'off-limits' to us mere developers (As was being able to make any kind of sensible design suggestions to the 'architect') but that is, as they say, 'Another story'.

                Anyway - as far as the Tomcat configuration is concerned, I usually put the datasource definition in the 'conf/server.xml' file and merely refer to this from the 'META-INF/context.xml' file, thereby allowing the same WAR file to be deployed to different tomcat servers, each of which is set up to hit a different database...

                '/conf/server.xml'
                Code:
                    <GlobalNamingResources>
                        .
                        .
                        .
                        <Resource
                            name="jdbc/fms"
                            type="javax.sql.DataSource"
                            password="password"
                            driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
                            maxIdle="2"
                            maxWait="5000"
                            username="username"
                            url="jdbc:sqlserver://server.domain:1433"
                            maxActive="10"/>
                        .
                        .
                        .
                    </GlobalNamingResources>

                'META-INF/context.xml'

                Code:
                <Context antiJARLocking="true" path="/fmswebapp">
                        .
                        .
                        .
                    <ResourceLink name="jdbc/fms" type="javax.sql.DataSource" global="jdbc/fms"/>
                        .
                        .
                        .
                </Context>
                (For the record - the 'antiJarLocking' attribute solves problems with redeployment where tomcat keeps jar files open, forcing a restart before deployment can take place.

                This situation may not apply in your case, as you use Tomcat/Weblogic, but I've found it a much better way to work as the configuration that is related purely to the deployment environment is completely removed from the 'binary' produced by the build process. All that the binary needs to know is the name of the datasource, from a JNDI point of view, not how or where it's configured.

                Enjoy!

                Comment


                • #9
                  javax.naming.NameNotFoundException

                  Hi there,

                  I'm getting the following exception while running my application:-

                  javax.servlet.ServletException: Exception forwarding for name welcome: javax.servlet.ServletException: javax.naming.NameNotFoundException: Name searchds is not bound in this Context
                  org.apache.jasper.runtime.PageContextImpl.doHandle PageException(PageContextImpl.java:825)
                  ....

                  It comes while I'm trying to connect the datasource "serachds" in http://localhost:8080/xxx/ where xxx.war is right there in the Tomcathome\webapps folder.

                  In the Tomcat Server Administratio tool page, I do have the following configuration for the Edit Data Source as:-

                  JNDI Name: jdbc/searchds
                  Data Source URL: jdbc:mysql://localhost:3306/search
                  JDBC Driver Class: com.mysql.jdbc.Driver

                  And in the resource link:-
                  Name: ds/searchds
                  Global: jdbc/searchds
                  Type: javax.sql.DataSource

                  Any help would be great.

                  Thanks in advance...

                  -Tsunami

                  Comment


                  • #10
                    according to
                    The format of the jndiName value is different for Tomcat - instead of 'jdbc/datasource-travelsystem', you need to use 'java:comp/env/jdbc/datasource-travelsystem'
                    That means if I have a development server using Tomcat and the testing server is using JBoss.
                    Does that means I have to modify ApplicationContext.xml everytime for each webapp before porting to testing server?
                    Is there an unify setting for both of them?

                    Comment


                    • #11
                      Unifying API

                      This is a good point. We also do NOT want multiple config files in our projects. We have deployed (gone live with) incorrect files before and we just need to shut that door and eliminate this potential.

                      Has anything been written that I've missed that handles this correctly? If not, I'm guessing we'll need to extend spring's datasource bean to handle this. I understand there are ways to address this but in a simple CVS | Eclipse | WTP/MAVEN | Tomcat | Weblogic environment, the last thing we want to do is continue the maddening multiple configs and just let ant or maven build the right thing:

                      web-dev.xml, web-test.xml, web-prod.xml
                      spring-dev.xml, spring-test.xml, spring-prod.xml
                      etc ...

                      In our world, the build needs to stay the build - consistent to push across all environments (that includes from localhost DEV which is most likely Eclipse, WTP and Tomcat all the way up to PRODUCTION from a maven build). We're close - Tomcat and Weblogic JNDI discrepencies are our current problem. We will use a work-around ... but it'd be great if this was handled natively in the Spring Framework.

                      Has anyone come up with a novel - nonHackish approach to handle this, what I'd think to be, common scenario?

                      Thanks.

                      I've wondered, why is Tomcat requiring the prefix? JEE convention? JEE standard? Is Weblogic not enforcing the standard? It seems to me Tomcat might offer a flag to turn this prefix off? Someone is spoiling interoperability if this is or is not a requirement for JEE compliance.
                      Last edited by lutherbaker; Sep 23rd, 2008, 08:22 AM.

                      Comment


                      • #12
                        Sorry for the brief reply - I'm a bit short on time at the moment.

                        To allow for the different naming conventions of JNDI resources on differeent servers (Weblogic/Tomcat etc), consider using PropertyPlaceholder to externalise that part of your config. Do a search of this forum for 'PropertyPlaceholder', as the subject has come up many times before.

                        If you get stuck, post back and I'll try to supply a more detailed explanation.

                        Comment


                        • #13
                          Well just wanted to say Thanks Very Much Bob.

                          After a day of investigating this and looking at your previous posts I finally found the following. Notice the "resourceRef" parameter for the Jndi Spring bean:

                          <bean id="webds" class="org.springframework.jndi.JndiObjectFactoryB ean">
                          <property name="jndiName" value="weblogicds" />
                          <property name="resourceRef" value="true" />
                          <property name="lookupOnStartup" value="true" />
                          </bean>

                          If resourceRef="true", the logic inside JndiObjectFactoryBean will append java:comp/env/ to the beginning of the name. Furthermore, if it cannot find a datasource there, it looks up the datasource directly!

                          That means, Tomcat works (java:comp/env/ namespace) AND weblogic works since the default behavior falls back to looking up the name directly. If you do not specific this parameter, it defaults to false .. in which case, it only looks up the name directly.

                          Again, your previous posts on tomcat's server.xml and context.xml were very helpful and helped me significantly as I tracked down managing this weblogic, tomcat and spring relationship for the dev team.

                          Spring scores a winner here ... elegant, built in and since tomcat uses META-INF/context.xml, I can commit this along with the project files so developers have one less thing to remember to manually/custom configure their environments.

                          Thanks again for your very fast response today.

                          Comment


                          • #14
                            Luther,

                            You're welcome - just helping others, as others have helped me before.

                            I just thought I'd add some more comments about reasons for favouring JNDI lookup over direct datasource definition.

                            Sometimes (Almost always, I'd hope) the connection string/username/password of the database instance used in production is different from that used in development/staging.
                            This information is also not likely to be known to the developer - for security reasons, and because it may change if the deployment architecture changes - so could not possibly be put into the spring context file.

                            Admittedly, this scenario could also be handled via a PropertyPlacholder solution, but the JNDI solution seems somehow cleaner to me.

                            I hope this makes sense.

                            Comment


                            • #15
                              JNDI Lookup Problems on Tomcat 5.5.9

                              This is the top-level entry point of the documentation bundle for the Apache Tomcat Servlet/JSP container. Apache Tomcat version 5.5 implements the Servlet 2.4 and JavaServer Pages 2.0 specifications from the Java Community Process, and includes many additional features that make it a useful platform for developing and deploying web applications and web services. Select one of the links from the navigation menu (to the left) to drill down to the more detailed documentation that is available. Each available manual is described in more detail below.


                              car zone
                              Last edited by car-zone; Apr 29th, 2009, 08:12 AM. Reason: Signature

                              Comment

                              Working...
                              X