Weblogic 10.3.6与Spring-web 4.0.3部署DataSource获取异常求助
解决Weblogic 10.3.6部署Spring项目时偶发JNDI DataSource查找失败的问题
我碰到过类似Weblogic和Spring整合的坑,结合你的问题场景和报错信息,整理了几个排查和解决的方向:
首先明确核心问题:你的Spring 4.0.3.RELEASE项目在Jetty上部署正常,但在Weblogic 10.3.6上偶发因JNDI查找不到数据源导致entityManagerFactory创建失败,重启有时能解决——这大概率是Weblogic的资源初始化时机、容器上下文适配或者类加载的问题,下面分点说明:
一、先搞定Weblogic端的JNDI数据源配置与部署顺序
- 调整部署优先级:如果你的war包比JNDI数据源先启动,Spring初始化时数据源还没准备好,自然查不到。可以在Weblogic控制台的「部署」页面点击「排序」,把JDBC数据源拉到war包前面,确保Spring启动前数据源已完成初始化。
- 核对JNDI名称与访问权限:报错显示
Resolved 'dummy'但找不到myDB,先去Weblogic控制台的「JDBC数据源」页面,确认配置的JNDI全名是不是dummy.myDB,避免拼写错误。另外要检查数据源的「目标服务器」是否包含你部署项目的服务器,否则全局数据源无法被项目访问。
二、优化Spring的JNDI查找逻辑,适配Weblogic容器
你现在手动创建InitialContext的方式不太适配Weblogic这类Java EE容器,建议换成Spring原生的JNDI工具类,稳定性更高:
方式1:用JndiObjectFactoryBean替代手动查找
@Bean public DataSource createWeblogicDatasource() { JndiObjectFactoryBean jndiFactory = new JndiObjectFactoryBean(); // 直接读取配置文件中的JNDI名称 jndiFactory.setJndiName(environment.getProperty("dsName")); // 开启资源引用,适配Weblogic的容器上下文规范 jndiFactory.setResourceRef(true); // 关闭启动时立即查找,改为第一次使用时再查询,避开部署时资源未就绪的问题 jndiFactory.setLookupOnStartup(false); // 缓存查找结果,避免重复查询 jndiFactory.setCache(true); jndiFactory.afterPropertiesSet(); return (DataSource) jndiFactory.getObject(); }
这种方式无需手动指定INITIAL_CONTEXT_FACTORY和PROVIDER_URL,Weblogic会自动注入容器上下文,比手动实现更可靠。
方式2:用@JndiLookup注解(Spring 4.0+支持)
你的Spring版本是4.0.3,刚好支持这个注解,写法更简洁:
@JndiLookup(jndiName = "${dsName}", resourceRef = true) private DataSource dataSource;
同样能自动适配Weblogic的JNDI环境,减少手动代码的出错概率。
三、排查Weblogic的类加载冲突问题
Weblogic 10.3.6基于Java EE 5规范,而Spring 4.0.3兼容Java EE 6,可能存在类加载冲突:
- 清理war包中的冗余依赖:确保war包不包含Weblogic已自带的类,比如
javax.naming、javax.servlet等。可以在pom.xml中将这些依赖的scope改为provided:
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.naming</groupId> <artifactId>jndi</artifactId> <version>1.2.1</version> <scope>provided</scope> </dependency>
- 调整类加载顺序:在Weblogic控制台进入项目部署→「部署描述符」→「Web应用程序」,将类加载顺序改为「父类加载器最后(Child First)」,避免Weblogic的旧版本类覆盖Spring的类,导致JNDI查找逻辑异常。
四、给JNDI查找加重试机制,应对偶发的资源未就绪
既然问题是偶发的,可以在原查找逻辑中添加重试,给Weblogic的数据源初始化留够时间:
@Bean private DataSource createWeblogicDatasource() throws NamingException { String contextFactory = environment.getProperty("jndiDriver"); String dsServer = environment.getProperty("dsServer"); String dsPort = environment.getProperty("dsPort"); String dsName = environment.getProperty("dsName"); String contextUrl = "t3://" + dsServer + ":" + dsPort; Hashtable ht = new Hashtable(); ht.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory); ht.put(Context.PROVIDER_URL, contextUrl); int retryCount = 3; // 重试3次 int retryDelay = 2000; // 每次间隔2秒 for (int i = 0; i < retryCount; i++) { try { Context ctx = new InitialContext(ht); DataSource dataSource = (DataSource) ctx.lookup(dsName); if (dataSource != null) { return dataSource; } } catch (NamingException e) { if (i == retryCount - 1) { // 最后一次重试失败,再抛出异常 throw e; } try { Thread.sleep(retryDelay); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } throw new NamingException("重试" + retryCount + "次后仍无法找到数据源"); }
这样即使第一次查找失败,也能多尝试几次,大概率能避开Weblogic数据源初始化的时间差问题。
内容的提问来源于stack exchange,提问作者Francesco
相关产品推荐
相关产品推荐

