从Web容器外部访问数据源(通过JNDI)
我正在尝试从容器外部的胖客户端访问Web容器(JBoss)中定义的数据源。
我决定通过JNDI查找数据源。实际上,我的持久性框架(Ibatis)可以做到这一点。
执行查询时,我总是最终会收到此错误:
java.lang.IllegalAccessException: Method=public abstract java.sql.Connection java.sql.Statement.getConnection() throws java.sql.SQLException does not return Serializable Stacktrace: org.jboss.resource.adapter.jdbc.remote.WrapperDataSourceService.doStatementMethod(WrapperDataSourceS ervice.java:411), org.jboss.resource.adapter.jdbc.remote.WrapperDataSourceService.invoke(WrapperDataSourceService.java :223), sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source), sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25), java.lang.reflect.Method.invoke(Method.java:585), org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155), org.jboss.mx.server.Invocation.dispatch(Invocation.java:94), org.jboss.mx.server.Invocation.invoke(Invocation.java:86), org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264), org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659),
我的数据源:
<?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <jndi-name>jdbc/xxxxxDS</jndi-name> <connection-url>jdbc:oracle:thin:@xxxxxxxxx:1521:xxxxxxx</connection-url> <use-java-context>false</use-java-context> <driver-class>oracle.jdbc.driver.OracleDriver</driver-class> <user-name>xxxxxxxx</user-name> <password>xxxxxx</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name> <min-pool-size>5</min-pool-size> <max-pool-size>20</max-pool-size> </local-tx-datasource> </datasources>
有谁知道这可能来自哪里?
也许有人甚至知道一种更好的方法来实现这一目标。
任何提示,不胜感激!
干杯,
麦可
解决方案
回答
我认为该异常表明我们尝试检索的SQLConnection对象未实现Serializable接口,因此无法按照我们要求的方式将其传递给我们。
从我对JDNI所做的有限工作来看,如果我们通过JNDI请求对象,则该对象必须可序列化。据我所知,如果我想到更好的方法,我将无法发布...
好的,一个显而易见的选择是在使用它的数据源本地提供一个可序列化的对象,但没有将数据源作为其可序列化对象图的一部分。然后胖客户端可以查找该对象并查询它。
或者创建一个(网络?)服务,通过该服务再次控制数据源的访问,胖客户端将访问该服务,如果我们担心这些问题,则可能会得到更好的封装和更可重用的方法。
回答
不确定这是否是相同的问题?
JBoss数据源配置
DataSource wrappers are not usable outside of the server VM
回答
@工具包:
好吧,不完全是。由于我可以通过JNDI访问数据源,因此它实际上是可见的,因此可以使用。
还是我弄错了什么?
@Brabster:
我认为我们在正确的轨道上。没有办法使连接可序列化吗?也许这只是一个配置问题...
回答
@Michael好吧,java.sql.Connection是一个接口,从技术上来说,我们从JBoss获得的具体实现可能是可序列化的,但是我不认为我们会真正拥有任何可用的选项。如果有可能,这可能很容易:)
我认为@toolkit可能已经在VM外部说出了可以使用的正确词,我认为JDBC驱动程序将与在底层OS中运行的本机驱动程序代码进行对话,因此这也许可以解释为什么我们不能仅仅通过其他地方的网络传递连接。
我的建议(如果我们没有更好的建议!)将是找到一种不同的方法,如果我们有权在JBoss目录中找到资源,也许实现一个代理对象,我们可以从该目录中找到并获取该对象。允许我们从胖客户端远程使用连接。我认为这是一种设计模式,称为数据传输对象,维基百科条目
回答
现在,我已经阅读了Ibatis的文章,也许我们可以实现Dao等的实现。可序列化,将其发布到目录中,然后检索它们并在胖客户端中使用它们?我们还将从中获得重用收益。
这是一个与Wicket相似的示例
回答
JBoss用自己的数据包包装了所有的数据源。
这样一来,它就可以通过autocommit发挥作用,从而从JDBC连接中获取指定的J2EE行为。它们大多是可序列化的。但是我们不必信任他们。
我会仔细看看它的包装纸。我已经为JBoss的JDBC的J2EE包装器包装程序编写了一个代理,该包装器与OOCJNDI一起使用,以使我的DAO代码单元可独立测试。
我们只需包装java.sql.Driver,将OOCJNDI指向类,然后在JUnit中运行。
驱动程序包装程序可以直接创建SQL驱动程序并委托给它。
返回我们自己在Connect上设计的java.sql.Connection包装器。
ConnectionWrapper可以包装Oracle驱动程序为我们提供的Connection,
它所做的所有特殊操作都将Autocommit设置为true。
别忘了Eclipse可以为我们代劳。添加我们需要委派给的成员,然后选择它并右键单击source-=> add delgage方法。
当我们通过电话付款时,这很棒;-)
Bada-bing,Bada-boom,JUnit开箱即用的J2EE测试。
问题可能也适用于同一件事,因为JUnit被划掉了,而FatCLient用蜡笔书写了。
我的FatClient使用xdoclet生成的RMI与J2EE服务器通信,所以我没有遇到问题。