Websphere 9上的Spring Boot数据源JNDI查找



我有一个Spring Boot应用程序,通常部署在Tomcat服务器上。现在我希望能够将其部署到Websphere 9上,尽管大多数时候它仍将部署在通常的Tomcat服务器上。我将应用程序打包为war,并通过管理界面将其部署到Websphere上,然后运行该应用程序。正如许多其他帖子所指出的那样,它不起作用是因为JNDI查找的工作方式不同。我尝试了各种各样的解决方案,但都不起作用。

我的数据源在Websphere中定义,名称为jdbc/foobar。我的查找是在我的Spring Boot应用程序中完成的:

JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource ds = dataSourceLookup.getDataSource("java:comp/env/jdbc/foobar");

这在Tomcat上工作,但在Websphere上不行。关于这个问题,其他SO帖子上的许多回答都说,对于Websphere,必须查找"jdbc/foobar";没有前缀(例如在回答的注释中),这是真的(我可以让它工作),但我希望代码与tomcat上的通常部署保持兼容。

作为旁注,如果没有前缀,getDataSource方法会自动添加前缀,这意味着我需要这样做:
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
dataSourceLookup.getJndiTemplate().getContext().lookup("jdbc/foobar");

这仍然是有用的,因为它工作得很好,它证明了我的问题是不是服务器端错误的数据源定义。

因为我希望我的代码保持相同的tomcat兼容代码,所以我保留了"java:comp/env/jdbc/foobar"查找,我查看了建议添加一些配置的答案,最值得注意的是这个。我找到了ibm-web- bind .xml文件,该文件是Websphere在部署时创建的,并放在WEB-INF文件夹中。我在那里添加了建议的resource-ref标签:

<?xml version="1.0" encoding="UTF-8"?>
<web-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://websphere.ibm.com/xml/ns/javaee"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd" version="1.0">
<virtual-host name="default_host"/>
<resource-ref name="jdbc/foobar" binding-name="jdbc/foobar" />
</web-bnd>

然后,因为我没有一个web.xml在我的战争,我尝试了@Resource技巧:

@Component
@Resource(name = "jdbc/foobar",type = javax.sql.DataSource.class)
public class MyServlet extends HttpServlet {

我可以验证servlet是正确加载的,但是Resource注释似乎没有做到这一点。然后我注意到Websphere在ibm-web- bind .xml文件旁边也创建了一个web.xml,所以我想我可能会尝试一下,并在里面添加了resource-ref标记(其余部分已经在这里,由Websphere添加):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<env-entry>
<env-entry-name>logback/context-name</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>main</env-entry-value>
</env-entry>
<listener>
<listener-class>ch.qos.logback.classic.selector.servlet.ContextDetachingSCL</listener-class>
</listener>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<resource-ref>
<description />
<res-ref-name>jdbc/foobar</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</web-app>

这仍然不起作用。我还注意到Websphere创建了另一个名为web_merged.xml的文件,该文件似乎将自动创建的web.xml与实际的web.xml合并(在我的情况下,实际的web.xml并不存在)。我试着把上面显示的代码也添加到这个文件中,但它并没有更好地工作。

现在,我不知道了。有人有其他想法吗,或者可能注意到我犯的一个明显的错误?

您在绑定文件中尝试的内容看起来应该已经工作了,假设您正在从指定绑定的相同web模块内执行查找(因为它是java:comp作用域)。

即便如此,您应该能够以完全标准的方式完成此操作,而根本不需要绑定文件(在这里很难获得所有语法正确),只需单独使用@Resource注释,

@Resource(name = "java:comp/env/jdbc/foobar", lookup = "jdbc/foobar", type = javax.sql.DataSource.class)

我建议去掉您正在试验的额外绑定/部署描述符,并尝试只使用注释,至少在开始时是这样。如果事实证明你不在同一个模块中,你可以使用java:app(如果在同一个应用程序中)或java:global代替java:comp,你需要在两个地方更新。

最新更新