- PR -

ContextからlookupでClassCastException

投稿者投稿内容
トリックスター
大ベテラン
会議室デビュー日: 2003/04/16
投稿数: 104
投稿日時: 2003-12-04 18:36
JNDIを使って、自作のクラスをContextにbindすることはできましたが、
ContextからlookupするとClassCastExceptionになってしまいます。
どなたか、ご指摘ください。あるいはサンプルの場所など教えてください。

---------------------------------------------------
// jndi.propertiesをロード
Properties jndiResource = new Properties();
jndiResource.load(AGDataSourceServer.class.getResourceAsStream(JNDI_RESOURCE_NAME));
// jndi.propertiesを指定してInitialContextを生成
context = new InitialContext(jndiResource);
// データソースをバインド
MyDataSource dataSource = new MyDataSource();
context.rebind(dataSourceName, dataSource);
System.out.println(dataSourceName + " binded.");
---------------------------------------------------
// jndi.propertiesをロード
Properties jndiResource = new Properties();
jndiResource.load(AGMqDataSource.class.getResourceAsStream(JNDI_RESOURCE_NAME));
// jndi.propertiesを指定してInitialContextを生成
Context context = new InitialContext(jndiResource);
// データソースを取得
dataSource = (MyDataSource)context.lookup(dataSourceName);
---------------------------------------------------

自作のクラス

・シグニチャ

public class MyDataSource implements MyConnector, Referenceable, Serializable

・Referenceableの実装

public Reference getReference() {
return new Reference(this.getClass().getName());
}

ちなみに、OracleDataSourceのbind/lookupは、同じ方法でできているので、
「自作のクラス」の実装の問題だと思っています。
足りない情報がございましたら、ご指摘ください。

よろしくお願いいたします。
Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2003-12-04 18:44
直接キャストするのではなく、
dataSource = (MyDataSource)PortableRemoteObject.narrow(dataSource,MyDataSource.class)を実行してみて下さい。


[ メッセージ編集済み 編集者: Emacs信者 編集日時 2003-12-04 18:50 ]
トリックスター
大ベテラン
会議室デビュー日: 2003/04/16
投稿数: 104
投稿日時: 2003-12-04 19:10
ご返答、ありがとうございます。

---------------------------------------------------
// jndi.propertiesをロード
Properties jndiResource = new Properties();
jndiResource.load(AGMqDataSource.class.getResourceAsStream(JNDI_RESOURCE_NAME));
// jndi.propertiesを指定してInitialContextを生成
Context context = new InitialContext(jndiResource);
// データソースを取得
Object ref = context.lookup(dataSourceName);
dataSource = (MyDataSource)PortableRemoteObject.narrow(ref, MyDataSource.class);
---------------------------------------------------
としてみたところ、今度は追加したPortableRemoteObject.narrow()の行で
ClassCastExceptionとなってしまいました。

jndi.propertiesは、こんな感じです。
---------------------------------------------------
java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory
java.naming.provider.url=rmi://localhost:XXXX
---------------------------------------------------

どうでしょうか?
Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2003-12-04 19:39
そうですか…
ClassCastExceptionは、キャスト部分で発生しているのか、narrowの内部で発生しているのか
どちらなんでしょうか。
あと、lookupで取得できたオブジェクトの型を調べなくてはなりませんね。
コード:
System.out.println( ref.getClass() ); //型情報を表示(1)

Object narrowed = PortableRemoteObject.narrow(ref,MyDataSource.class);

System.out.println( narrowed.getClass() ); //型情報を表示(2)

MyDataSource mds = (MyDataSource) narrowed;


こんな感じでどうでしょうか。
トリックスター
大ベテラン
会議室デビュー日: 2003/04/16
投稿数: 104
投稿日時: 2003-12-04 19:50
リアルタイムでお答えいただき、ありがとうございます。

型情報を表示(1)は、
class javax.naming.Reference
と表示され、
PortableRemoteObject.narrow()でClassCastExceptionとなり、
型情報を表示(2)は、表示されません。

いかがでしょうか?
トリックスター
大ベテラン
会議室デビュー日: 2003/04/16
投稿数: 104
投稿日時: 2003-12-04 20:13
どうもです。

補足
ref.getClassName()は、
xxxx.MyDataSource

ref.getFactoryClassLocation()は、
null

ref.getFactoryClassName()は、
null

ref.getAll()は、空でした。
Emacs信者
常連さん
会議室デビュー日: 2003/08/10
投稿数: 38
投稿日時: 2003-12-04 21:15
MyDataSourceを以下のように変更すれば、実行できました。

コード:

//変更前
public class MyDataSource implements MyConnector,Referenceable,Serializable{
public MyDataSource(){
//なにもなし
}

public Reference getReference(){
//getReferenceの実装
}

/* その他の、MyDataSourceの実装 */
}

//変更後
public class MyDataSource extends Reference implements MyConnector{
public MyDataSource(){
super( MyDataSource.class.getName() );
}

/* その他の、MyDataSourceの実装 */
}



ちなみに、あくまでもReferenceableをimplementする方法(変更前の方法)で行く場合は、
javax.naming.spi.ObjectFactoryを実装するクラスを作成したりする必要があるなど、
かなり面倒なのでオススメできません。

でも、なにか違うような…
そもそも、自分でReferenceを継承したりとかする必要があるのでしょうか。
これって本来は、アプリケーションサーバ側(プロバイダ側)がやる仕事のような気がします。


[ メッセージ編集済み 編集者: Emacs信者 編集日時 2003-12-04 21:30 ]
トリックスター
大ベテラン
会議室デビュー日: 2003/04/16
投稿数: 104
投稿日時: 2003-12-04 23:51
手際よく応えていただいていたのに、間があいてしまってすいません。

教えていただいた修正をしました。
しかし、今度は別の問題が発生しました。
自分で解決しようと思ったのですが、どうもうまくいきません。
自分でも頑張ってみますが、書くだけ書かせてください。
すぐにわかるようでしたら、知恵をお貸しください。

MyDataSourceの保持しているオブジェクトがSerializableインターフェースを
実装していなかったので、下記のような例外がスローされます。
ですから、implements Serializableとしました。
するとそのまた子供がSerializableではありませんでした。
ですから、implements Serializableとしました。
それを続けていると他社製品のクラスまできてしまいました。
それは変更できないので、試しに transientとしました。
予想通りNullPointerExceptionがスローされました。
どう対処してよいのか行き詰まっております。

別スレッドたてた方がよいですかね。

javax.naming.CommunicationException. Root exception is java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.io.WriteAbortedException: Writing aborted by exception; java.io.NotSerializableException: xx.xxx.xxxx.Xxxxx
java.io.WriteAbortedException: Writing aborted by exception; java.io.NotSerializableException: xx.xxx.xxxx.Xxxxx
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
at java.io.ObjectInputStream.inputClassFields(ObjectInputStream.java:2258)
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:514)
at java.io.ObjectInputStream.inputObject(ObjectInputStream.java:1407)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:381)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:231)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:295)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:129)
at com.sun.jndi.rmi.registry.ReferenceWrapper_Stub.getReference(Unknown Source)
at com.sun.jndi.rmi.registry.RegistryContext.decodeObject(RegistryContext.java:415)
at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:92)
at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:96)
at javax.naming.InitialContext.lookup(InitialContext.java:345)
at xxxx.MyDataSource.getInstance(MySource.java:60)
     :

スキルアップ/キャリアアップ(JOB@IT)