从 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>
有人知道这可能来自哪里吗?
也许有人甚至知道如何实现这一目标的更好方法。 非常感谢任何提示!
干杯,
迈克尔
I'm trying to access a data source that is defined within a web container (JBoss) from a fat client outside the container.
I've decided to look up the data source through JNDI. Actually, my persistence framework (Ibatis) does this.
When performing queries I always end up getting this error:
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),
My Datasource:
<?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>
Does anyone have a clue where this could come from?
Maybe someone even knows a better way how to achieve this.
Any hints are much appreciated!
Cheers,
Michael
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
JBoss 用它自己的数据源包装所有数据源。
这让它可以利用自动提交来从 JDBC 连接中获取指定的 J2EE 行为。 它们大部分是可序列化的。 但你不必相信他们。
我会仔细看它的包装。 我已经为 JDBC 的 JBoss J2EE 包装器编写了一个代理,它与 OOCJNDI 一起使用,以使我的 DAO 代码可以独立进行单元测试。
您只需包装 java.sql.Driver,将 OOCJNDI 指向您的类,然后在 JUnit 中运行。
Driver 包装器可以直接创建 SQL Driver 并委托给它。
返回您自己在 Connect 上设计的 java.sql.Connection 包装器。
ConnectionWrapper 可以只包装 Oracle 驱动程序提供给您的连接,
它的特殊之处在于将 Autocommit 设置为 true。
不要忘记 Eclipse 可以为您做代理。 添加您需要委派的成员,然后选择它并右键单击,source -=>add delgage 方法。
当您通过线路获得报酬时,这非常棒;-)
Bada-bing、Bada-boom、JUnit 开箱即用的 J2EE 测试。
您的问题可能与同样的问题有关,将 JUnit 划掉并用蜡笔写下 FatCLient。
我的 FatClient 使用 xdoclet 生成的 RMI 与 J2EE 服务器通信,所以我没有遇到您的问题。
JBoss wraps up all DataSources with it's own ones.
That lets it play tricks with autocommit to get the specified J2EE behaviour out of a JDBC connection. They are mostly serailizable. But you needn't trust them.
I'd look carefully at it's wrappers. I've written a surrogate for JBoss's J2EE wrappers wrapper for JDBC that works with OOCJNDI to get my DAO code unit test-able standalone.
You just wrap java.sql.Driver, point OOCJNDI at your class, and run in JUnit.
The Driver wrapper can just directly create a SQL Driver and delegate to it.
Return a java.sql.Connection wrapper of your own devising on Connect.
A ConnectionWrapper can just wrap the Connection your Oracle driver gives you,
and all it does special is set Autocommit true.
Don't forget Eclipse can wrt delgates for you. Add a member you need to delegate to , then select it and right click, source -=>add delgage methods.
This is great when you get paid by the line ;-)
Bada-bing, Bada-boom, JUnit out of the box J2EE testing.
Your problem is probably amenable to the same thing, with JUnit crossed out and FatCLient written in an crayon.
My FatClient uses RMI generated with xdoclet to talk to the J2EE server, so I don't have your problem.
我现在已经阅读了 Ibatis - 也许您可以使 Dao 等的实现可序列化,将它们发布到您的目录中,然后检索它们并在您的胖客户端中使用它们? 您也可以从中获得重用的好处。
以下是 Wicket 类似的示例
I've read up on Ibatis now - maybe you can make your implementations of Dao etc. Serializable, post them into your directory and so retrieve them and use them in your fat client? You'd get reuse benefits out of that too.
Here's an example of something looks similar for Wicket
@工具包:
嗯,不完全是。 由于我可以通过 JNDI 访问数据源,因此它实际上是可见的,因此可用。
或者我完全错了?
@布拉布斯特:
我认为你走在正确的道路上。 有没有办法使连接可序列化? 也许这只是一个配置问题......
@toolkit:
Well, not exactly. Since I can access the data source over JNDI, it is actually visible and thus usable.
Or am I getting something totally wrong?
@Brabster:
I think you're on the right track. Isn't there a way to make the connection serializable? Maybe it's just a configuration issue...
我认为该异常表明您尝试检索的 SQLConnection 对象未实现 Serialized 接口,因此无法按照您要求的方式将其传递给您。
从我使用 JDNI 所做的有限工作来看,如果您通过 JNDI 请求一个对象,它必须是可序列化的。 据我所知,没有办法解决这个问题 - 如果我想到更好的方法,我会将其发布...
好吧,一个明显的选择是提供一个使用它但不使用它的数据源本地的可序列化对象将数据源作为其可序列化对象图的一部分。 然后,胖客户端可以查找该对象并查询它。
或者创建一个(Web?)服务来管理访问数据源 - 您的胖客户端将再次访问该服务 - 如果您担心这些问题,这可能会是更好的封装和更可重用的方法。
I think the exception indicates that the SQLConnection object you're trying to retrieve doesn't implement the Serializable interface, so it can't be passed to you the way you asked for it.
From the limited work I've done with JDNI, if you're asking for an object via JNDI it must be serializable. As far as I know, there's no way round that - if I think of a better way I'll post it up...
OK, one obvious option is to provide a serializable object local to the datasource that uses it but doesn't have the datasource as part of its serializable object graph. The fat client could then look up that object and query it instead.
Or create a (web?) service through which to access the datasource is governed - again your fat client would hit the service - this would probably be better encapsulated and more reuseable approach if those are concerns for you.
@Michael嗯,java.sql.Connection是一个接口 - 从技术上讲,您从 JBoss 获得的具体实现可能是可序列化的 - 但我不认为您真的会有任何可以使用的选项。 如果可能的话,这可能很容易:)
我认为@toolkit可能已经说了正确的话,可以在虚拟机之外使用——我猜JDBC驱动程序将与运行在底层操作系统中的本机驱动程序代码进行对话,所以这可以解释为什么你不能只通过网络在其他地方传递连接。
我的建议(如果您没有得到任何更好的建议!)是找到一种不同的方法 - 如果您有权在 JBoss 目录上找到资源,也许可以实现一个可以从目录中找到并获取的代理对象这允许您从胖客户端远程使用连接。 我认为这是一种称为数据传输对象的设计模式维基百科条目
@Michael Well, java.sql.Connection is an Interface - it might technically be possible for the concrete implementation you're getting from JBoss to be Serializable - but I don't think you're really going to have any options you can use. If it was possible, it would probably be easy :)
I think @toolkit might have said the right words with useable outside the VM - the JDBC drivers will be talking to native driver code running in the underlying OS I guess, so that might explain why you can't just pass a connection over the network elsewhere.
My advice, (if you don't get any better advice!) would be to find a different approach - if you have access to locate the resource on the JBoss directory, maybe implement a proxy object that you can locate and obtain from the directory that allows you to use the connection remotely from your fat client. That's a design pattern called data transfer object I think Wikipedia entry
不确定这是否是同一个问题?
JBoss 数据源配置
Not sure if this is the same issue?
JBoss DataSource config