Announcement Announcement Module
Collapse
No announcement yet.
Problem with JndiObjectFactoryBean and WebSphere Datasource Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with JndiObjectFactoryBean and WebSphere Datasource

    Hi, I'm using Spring 1.1.5 with a WebSphere 5.0 web container.

    I originally configured a DataSource bean using Jakarta's DBCP and everything worked fine.

    I've just reconfigured the DataSource bean to use a WebSphere DataSource via JNDI and it doesn't work.

    The applicationContext.xml has the following entries:

    <bean id="ibDataSource" class="org.springframework.jndi.JndiObjectFactoryB ean">
    <property name="jndiName"><value>jdbc/IB</value></property>
    <property name="resourceRef"><value>false</value></property>
    </bean>
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTran sactionManager"/>

    Later on in the same file I define a bean that uses the ibDataSource bean:

    <bean id="eventLogConfigDao" class="nz.co.bnz.ib.integration.eventlog.db.EventL ogConfigDaoJdbc">
    <property name="dataSource">
    <ref bean="ibDataSource" />
    </property>
    </bean>

    When Spring starts up (via org.springframework.web.context.ContextLoaderServl et), it attempts to load these beans. The first two load fine, but the eventLogConfigDao bean gets an exception when setting the dataSource property:

    [28/04/05 10:49:38:015 NZST] 7dea382b SystemOut O INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
    [28/04/05 10:49:38:015 NZST] 7dea382b WebGroup I SRVE0180I: [IBWebApp] [/IBWebApp] [Servlet.LOG]: Loading Spring root WebApplicationContext
    [28/04/05 10:49:38:124 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.xml.XmlBeanDefin itionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]
    [28/04/05 10:49:38:343 NZST] 7dea382b SystemOut O INFO org.springframework.web.context.support.XmlWebAppl icationContext - Bean factory for application context [org.springframework.web.context.support.XmlWebAppl icationContext;hashCode=1644148779]: org.springframework.beans.factory.support.DefaultL istableBeanFactory defining beans [ibServiceContext,ibDataSource,transactionManager,i bGCSInterface,eventLogConfigDao,bnz.ib.eventlogcon fig,ibSQLInterface,ibErrorMapper,ibSessionHandler, ibLogin]; root of BeanFactory hierarchy
    [28/04/05 10:49:38:343 NZST] 7dea382b SystemOut O INFO org.springframework.web.context.support.XmlWebAppl icationContext - 10 beans defined in application context [org.springframework.web.context.support.XmlWebAppl icationContext;hashCode=1644148779]
    [28/04/05 10:49:38:343 NZST] 7dea382b SystemOut O INFO org.springframework.core.CollectionFactory - Using JDK 1.3 collections
    [28/04/05 10:49:38:359 NZST] 7dea382b SystemOut O INFO org.springframework.web.context.support.XmlWebAppl icationContext - Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMess ageSource@106ff829]
    [28/04/05 10:49:38:359 NZST] 7dea382b SystemOut O INFO org.springframework.web.context.support.XmlWebAppl icationContext - Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicatio nEventMulticaster@17ee7829]
    [28/04/05 10:49:38:359 NZST] 7dea382b SystemOut O INFO org.springframework.ui.context.support.UiApplicati onContextUtils - No ThemeSource found for [org.springframework.web.context.support.XmlWebAppl icationContext;hashCode=1644148779]: using ResourceBundleThemeSource
    [28/04/05 10:49:38:359 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Pre-instantiating singletons in factory [org.springframework.beans.factory.support.DefaultL istableBeanFactory defining beans [ibServiceContext,ibDataSource,transactionManager,i bGCSInterface,eventLogConfigDao,bnz.ib.eventlogcon fig,ibSQLInterface,ibErrorMapper,ibSessionHandler, ibLogin]; root of BeanFactory hierarchy]
    [28/04/05 10:49:38:359 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Creating shared instance of singleton bean 'ibServiceContext'
    [28/04/05 10:49:38:671 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Creating shared instance of singleton bean 'ibDataSource'
    [28/04/05 10:49:38:734 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Creating shared instance of singleton bean 'transactionManager'
    [28/04/05 10:49:38:765 NZST] 7dea382b SystemOut O INFO org.springframework.transaction.jta.JtaTransaction Manager - Using JTA UserTransaction [com.ibm.ejs.jts.jta.UserTransactionImpl@4fa37827] from JNDI location [java:comp/UserTransaction]
    [28/04/05 10:49:38:765 NZST] 7dea382b SystemOut O INFO org.springframework.transaction.jta.JtaTransaction Manager - No JTA TransactionManager specified: transaction suspension not available
    [28/04/05 10:49:38:765 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Creating shared instance of singleton bean 'ibGCSInterface'
    [28/04/05 10:49:40:202 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Creating shared instance of singleton bean 'eventLogConfigDao'
    [28/04/05 10:49:40:234 NZST] 7dea382b SystemOut O INFO org.springframework.beans.factory.support.DefaultL istableBeanFactory - Destroying singletons in factory {org.springframework.beans.factory.support.Default ListableBeanFactory defining beans [ibServiceContext,ibDataSource,transactionManager,i bGCSInterface,eventLogConfigDao,bnz.ib.eventlogcon fig,ibSQLInterface,ibErrorMapper,ibSessionHandler, ibLogin]; root of BeanFactory hierarchy}
    [28/04/05 10:49:40:234 NZST] 7dea382b SystemOut O ERROR org.springframework.web.context.ContextLoader - Context initialization failed
    org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'eventLogConfigDao' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyAccessExceptions Exception: PropertyAccessExceptionsException (1 errors); nested propertyAccessExceptions are: [org.springframework.beans.TypeMismatchException: Failed to convert property value of type [com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource] to required type [javax.sql.DataSource] for property 'dataSource']
    PropertyAccessExceptionsException (1 errors)

    org.springframework.beans.TypeMismatchException: Failed to convert property value of type [com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource] to required type [javax.sql.DataSource] for property 'dataSource'
    at org.springframework.beans.BeanWrapperImpl.doTypeCo nversionIfNecessary(BeanWrapperImpl.java:1016)
    at org.springframework.beans.BeanWrapperImpl.setPrope rtyValue(BeanWrapperImpl.java:779)
    at org.springframework.beans.BeanWrapperImpl.setPrope rtyValue(BeanWrapperImpl.java:685)
    at org.springframework.beans.BeanWrapperImpl.setPrope rtyValue(BeanWrapperImpl.java:826)
    at org.springframework.beans.BeanWrapperImpl.setPrope rtyValues(BeanWrapperImpl.java:853)
    at org.springframework.beans.BeanWrapperImpl.setPrope rtyValues(BeanWrapperImpl.java:842)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:870)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:688)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:325)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:260)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:221)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:145)
    at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:291)
    at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:317)
    at org.springframework.web.context.support.AbstractRe freshableWebApplicationContext.refresh(AbstractRef reshableWebApplicationContext.java:131)
    at org.springframework.web.context.ContextLoader.crea teWebApplicationContext(ContextLoader.java:224)
    at org.springframework.web.context.ContextLoader.init WebApplicationContext(ContextLoader.java:150)
    at org.springframework.web.context.ContextLoaderServl et.init(ContextLoaderServlet.java:81)
    at javax.servlet.GenericServlet.init(GenericServlet.j ava:258)
    at com.ibm.ws.webcontainer.servlet.StrictServletInsta nce.doInit(StrictServletInstance.java:82)
    at com.ibm.ws.webcontainer.servlet.StrictLifecycleSer vlet._init(StrictLifecycleServlet.java:147)
    at com.ibm.ws.webcontainer.servlet.PreInitializedServ letState.init(StrictLifecycleServlet.java:270)
    at com.ibm.ws.webcontainer.servlet.StrictLifecycleSer vlet.init(StrictLifecycleServlet.java:113)
    at com.ibm.ws.webcontainer.servlet.ServletInstance.in it(ServletInstance.java:189)
    at javax.servlet.GenericServlet.init(GenericServlet.j ava:258)
    at com.ibm.ws.webcontainer.webapp.WebAppServletManage r.addServlet(WebAppServletManager.java:876)
    at com.ibm.ws.webcontainer.webapp.WebAppServletManage r.loadServlet(WebAppServletManager.java:224)
    at com.ibm.ws.webcontainer.webapp.WebAppServletManage r.loadAutoLoadServlets(WebAppServletManager.java:5 42)
    at com.ibm.ws.webcontainer.webapp.WebApp.loadServletM anager(WebApp.java:1272)
    at com.ibm.ws.webcontainer.webapp.WebApp.init(WebApp. java:277)
    at com.ibm.ws.webcontainer.srt.WebGroup.loadWebApp(We bGroup.java:400)
    at com.ibm.ws.webcontainer.srt.WebGroup.init(WebGroup .java:218)
    at com.ibm.ws.webcontainer.WebContainer.addWebApplica tion(WebContainer.java:1004)
    at com.ibm.ws.runtime.component.WebContainerImpl.inst all(WebContainerImpl.java:136)
    at com.ibm.ws.runtime.component.WebContainerImpl.star t(WebContainerImpl.java:356)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl.st art(ApplicationMgrImpl.java:415)
    at com.ibm.ws.runtime.component.DeployedApplicationIm pl.fireDeployedObjectStart(DeployedApplicationImpl .java:808)
    at com.ibm.ws.runtime.component.DeployedModuleImpl.st art(DeployedModuleImpl.java:351)
    at com.ibm.ws.runtime.component.DeployedApplicationIm pl.start(DeployedApplicationImpl.java:578)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl.st artApplication(ApplicationMgrImpl.java:268)
    at com.ibm.ws.runtime.component.ApplicationMgrImpl.st artApplication(ApplicationMgrImpl.java:485)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.tivoli.jmx.modelmbean.MMBInvoker.invoke(MMBInv oker.java:46)
    at com.tivoli.jmx.modelmbean.MMBInvoker.invokeOperati on(MMBInvoker.java:115)
    at com.tivoli.jmx.modelmbean.DynamicModelMBeanSupport .invoke(DynamicModelMBeanSupport.java:409)
    at javax.management.modelmbean.RequiredModelMBean.inv oke(RequiredModelMBean.java:323)
    at com.tivoli.jmx.GenericMBeanSupport.invoke(GenericM BeanSupport.java:178)
    at com.tivoli.jmx.MBeanAccess.invoke(MBeanAccess.java :113)
    at com.tivoli.jmx.MBeanServerImpl.invoke(MBeanServerI mpl.java:290)
    at com.ibm.ws.management.AdminServiceImpl.invoke(Admi nServiceImpl.java:658)
    at com.ibm.ws.management.connector.AdminServiceDelega tor.invoke(AdminServiceDelegator.java:130)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.ibm.ws.management.connector.soap.SOAPConnector .invoke(SOAPConnector.java:306)
    at com.ibm.ws.management.connector.soap.SOAPConnector .service(SOAPConnector.java:178)
    at com.ibm.ws.management.connector.soap.SOAPConnectio n.handleRequest(SOAPConnection.java:55)
    at com.ibm.ws.http.HttpConnection.readAndHandleReques t(HttpConnection.java:615)
    at com.ibm.ws.http.HttpConnection.run(HttpConnection. java:439)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.j ava:672)

    I've checked com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource. It implements com.ibm.websphere.rsadapter.WSDataSource, which in turn extends javax.sql.DataSource. So it should work.

    Any ideas?

    Cheers,
    Dunc

  • #2
    Duncan

    This sounds like a class loading problem. I would suggest trying to cut down to the simplest possible form of it--write a servlet that does that JNDI lookup and tries to cast the result to javax.sql.DataSource...

    You could also write a little bit of code to walk the ClassLoader hierarchy and try to output a description of it...

    Sorry I can't be more specific, but I think a bit more digging is necessary. Unfortunately I don't have a WebSphere installation handy, so I can't try to reproduce it.

    Rgds
    Rod

    Comment


    • #3
      Thanks Rod, it is indeed a ClassLoader problem.

      I've changed the Classloader mode in WebSphere from PARENT_LAST back to the WebSphere default of PARENT_FIRST, and the problem disappeared.

      However, there is a reason we explicitly it set to PARENT_LAST so this fix causes another, unacceptable, problem.

      WebSphere uses Jakarta Commons Logging. So does Spring and our application code. If we don't change the Classloader mode from WebSphere's default of PARENT_FIRST to PARENT_LAST, the JCL code in Spring and our app picks up the WebSphere logging instead of the setup we've specified in the app (using log4j via a commons-logging.properties file). This is a well known issue when using JCL with WebSphere. IBM's recommended workaround for each Web App is to set the class loader mode to PARENT_LAST and create a commons-logging.properties file to force JCL to use a separate instance from the WebSphere one.

      I'll have a look at why the PARENT_LAST setting seems to prevent the child class loader from seeing the WebSphere Datasource class in the parent class loader after it (presumably) fails to find it in the child class loader. I suspect it has something to do with the jars being deployed with the app. However I haven't had a chance to look into it yet as I've been out of the office for a few days.

      Comment


      • #4
        Found the problem.

        If I have the oracle jdbc jar in the WEB-INF/lib, and the PARENT_LAST setting in WebSphere for the WAR's classloader mode, then Spring fails to cast the WebSphere provided com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource object to the expected bean property of javax.sql.DataSource.

        If I take the oracle jar out, or change the classloader for the WAR back to PARENT_FIRST, it works fine.

        PARENT_LAST forces the child classloader to use the copy of javax.sql.DataSource in the oracle jar when this jar is present. This copy appears to be different from the one provided with the WebSphere runtime, hence the casting problem.

        PARENT_FIRST forces the child classloader to use the copy of javax.sql.DataSource in the parent classloader first, regardless of the presence of the oracle jar. This is always the WebSphere provided one, hence the successful casting in this scenario.

        I have another app that has the same scenario, minus Spring and it works fine with the oracle jar and PARENT_LAST setting. It casts the DataSource to javax.sql.DataSource just fine. So there must be something about the way that Spring does it that is different.

        Not sure where I'll go from here, as my Spring-based app currently requires both the oracle jar and the PARENT_LAST setting. But at least I know what the problem is now and can work on a solution.

        Thanks,
        Duncan

        Comment


        • #5
          For what it's worth, I wrestled for a week with PARENT_LAST trying to override Websphere's default and proprietary Jakarta Commons logging configuration and eventually gave up, opting instead to use Log4J directly and PARENT_FIRST.

          Scott

          Comment


          • #6
            FYI I've now solved the problem to my satisfaction.

            The IBM support site has the following article on the JCL vs WebSphere issue: http://www-1.ibm.com/support/docview...id=swg27004610.

            Of the 3 options covered in that article, I was using option 3. However, option 2 works just as well and it solves my DataSource problem because it also works with the PARENT_FIRST class loader setting.

            Just to clarify this, I now have my EAR and WAR classloader modes both at the default of PARENT_FIRST, and the WAR classload policy at the default of MODULE. I have the JCL and dependent jars in my WEB-INF/lib. I have a file named org.apache.commons.logging.LogFactory in the WEB-INF/services directory. The oracle jar that I need for some of my classes is also in WEB-INF/lib.

            With this config, the JCL in my Spring-based app pickups up the app specific JCL config instead of WebSphere's, and the com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource returned by Spring's JndiObjectFactoryBean is successfully resolved as a javax.sql.DataSource when passed to the other beans by the BeanFactory.

            Thanks,
            Duncan

            Comment

            Working...
            X