Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

EJB return value generating ClassCastException!

Options
  • 27-03-2002 9:29pm
    #1
    Closed Accounts Posts: 1,322 ✭✭✭


    Hi,

    I am having a bit of a problem ATM with a stateless session bean. The bean performs quick DB stuff on behalf of a client app. Just like connecting to a DB in java, I'm using a Statement object to execute queries, which if successful returns a ResultSet. The problem lies in that when the bean container connects to the DB (cloudscape), it uses RMIJdbc (this is not the problem), the problem is that when you call the Statement.executeQuery(String sql) method you should get a ResultSet interface back. I'm not, and instead I am getting a RJResultSet, and when I pass this back to the client program and try to cast it to an object of the type ResultSet, it throws the exception.

    I know I can't cast RJResultSet because, it is a class that merely implements the ResultSet interface (they are two different things). But basically what the method in my bean is trying to do is the following:

    public ResultSet lookupDB(String search_parameter), for example. That method, makes a connection to cloudscape, sends some SQL, and expects a ResultSet back. It then returns that ResultSet to the client App. But the problem is that it's not a ResultSet, it's a RJResultSet.

    So then I thought to myself, maybe I can't return an interface, and that's why RJResultSet was used, so I can return an object ref instead. My problem lies in that, in the client app, I cant instanciate an RJResultSet to take the return value back from the bean. This is because the definition for the class does not exist anywhere on my classpath. I can't find it anywhere, and this makes me wonder how the hell does the EJB get it. If the App Server environent is using the same classpath string as the client app.

    I know the connection between the EJB and DB are OK, because I can send simple SQL commands that don't expect a ResultSet, such as a CREATE/DELETE/UPDATE etc., but when I try and do a query using SELECT for example, it's a different story alltogether.

    Help plz :(

    ;-phobos-)


Comments

  • Registered Users Posts: 1,931 ✭✭✭Zab


    Hi.

    Java defines several interfaces that are used to communicate with JDBC Drivers ( Connection, Statement, ResultSet etc ). Whenever you use or get an instance of one of these interfaces, it is always an instance of another class that implements these interfaces. This class is provided by whoever made the JDBC Driver that you are using ( RMIJdbc in your case ).

    You are using Statement.executeQuery(), which returns an object that implements the ResultSet interface. There is no need to cast this object as a ResultSet because:
    1. It is already cast as a result set
    2. You do not need an explicit cast to up cast
    I know I can't cast RJResultSet because, it is a class that merely implements the ResultSet interface (they are two different things). But basically what the method in my bean is trying to do is the following:
    I don't know whether you are trying to cast a ResultSet to a RJResultSet, or a RJResultSet to a ResultSet here, but you should be able to do it either way ( presuming the object is a RJResultSet in reality ). However, I do think that you don't have to worry about RJResultSet's at all, unless there is a bug within the class's code ( you can probably get the source off objectweb's website ).

    So then I thought to myself, maybe I can't return an interface
    You can....
    My problem lies in that, in the client app, I cant instanciate an RJResultSet
    You should be able to get this from the org.objectweb.rmijdbc package....although I don't see why you would want to as you already seem to have an instance of the class. It probably doesn't have a default constuctor anyway.


    I don't think your problem lies with any of this....or perhaps I'm missing something in what your saying...and are you sure that you are trying to cast to a java.sql.ResultSet and not some other ResultSet? The thing is, what you are saying is, afaik, impossible: That an instance of RJResultSet, which implements java.sql.ResultSet will throw a ClassCastException when cast as a java.sql.ResultSet.

    Zab.


  • Closed Accounts Posts: 1,322 ✭✭✭phobos


    Cheers for the help zab. I headed off and had a read on objectweb's site wrt RmiJdbc. RJResultSet is a class of the package RmiJdbc which (you are right can be downloaded from their site, but I already have it [it comes with the J2EE jdk]). It also says that an RJResultSet is a class that implements java.sql.ResultSet. When I instanciate an instance of java.sql.Statement, and invoke it's executeQuery method, I expected a java.sql.ResultSet back. But because I'm using RmiJdbc, I got a RJResultSet back. In the remote interface/bean implementation classes I have defined the method to return a java.sql.ResultSet.

    In the client program I have a line like this:
    ResultSet rs = remoteBean.lookupDB("phobos");

    It is when I run this code the following is generated: java.lang.ClassCastException: RmiJdbc.RJResultSet

    So I'm afraid I can't cast a RJResultSet to a ResultSet :(

    At this point I'm flustered because AFAIK, the bean has been able to write to the DB, but I can't determine if anything is in there. This is because no exceptions are being thrown for the methods that don't return a ResultSet.

    Any further ideas?

    ;-phobos-)


  • Registered Users Posts: 1,931 ✭✭✭Zab


    Hmmm...Ok.

    What if you try and use the result set within the bean. Ie. make sure that it works with some simple operations, and perhaps try the cast. What I'm thinking is that it sounds like some annoying serialization problem, so it would be nice to make sure that it is this, and not some other problem.

    Presuming that it is a serialization problem, I guess you could try importing RJResultSet and returning one of these instead of the ResultSet, the logic behind this being that it will have to be a RJResultSet instead of any other ResultSet because RJResultSet's are serializable, and other's aren't.

    Zab.


  • Registered Users Posts: 15,443 ✭✭✭✭bonkey


    Originally posted by phobos
    In the client program I have a line like this:
    ResultSet rs = remoteBean.lookupDB("phobos");

    Am I being dim here, or should that not be :

    ResultSet rs = (ResultSet) remoteBean.lookupDB("phobos");

    so that you're explicitly casting the returned value?

    I seem to recall that not explicitly casting it would, indeed, return a classCast error.

    I could of course, be very very dim at the moment.

    jc


  • Closed Accounts Posts: 1,322 ✭✭✭phobos


    bonkey, the line in my last post is correct, becuase the method is defined to return a ResultSet:

    public ResultSet lookupAccount(String username) throws RemoteException; (That's in the remote interface of the EJB, and also in the Bean implementation class).

    Also Zab I thought about the Serialization issue already, and tried using RJResultSets instead (as both a return value from the lookupDB method, and in the client). But the problem there is, when I try to compile it, I am getting class def's not found errors. So then I parsed along my current classpath, to see if it existed (and it does). It's packaged in RmiJdbc.RJResultSet, which is referenced on my classpath. But for some reason when I try and use it in a program, it tells me it knows nothing of it.

    I am guessing the reason RJResultSet and all the other RmiJdbc.* classes are in existence is because the standard java.sql.* methods cannot be used over a distributed environment using protocols such as RMI.

    This problem is soooo stupid, and small but it causing big problems. If I could get this working, I should be able to get this project out of the way in a matter of a day or two. :(

    Any further ideas. I appreciate your contributions so far :)

    ;-phobos-)


  • Advertisement
  • Registered Users Posts: 15,443 ✭✭✭✭bonkey


    Originally posted by phobos
    bonkey, the line in my last post is correct, becuase the method is defined to return a ResultSet:

    public ResultSet lookupAccount(String username) throws RemoteException; (That's in the remote interface of the EJB, and also in the Bean implementation class).

    My bad. I must have misunderstood you in the first post - I thought you were returnng an RJrs, and trying to cast on the client to an rs.

    Anyway.....you wont be able to return a ResultSet from the EJB, cause all parameters and return values for an EJB must be serialisable, yeah? This line of thinking would probably have been why I was thinking that you werent returning a ResultSet....because it isnt explicitly serializable (being an interface n all).

    So - given that you said what you are in fact returning is an RJResultSet (which implements ResultSet, yeah), could you not return an RJResultSet (which is serializable) only assign it into an Object object, rather than a ResultSet. Then try explicitly assigning that object to a ResultSet object, using casting.

    I'm not even sure I'm explaining myself well here, though, and you'll probably end up with the same problem if your client app cant see that class for some stupid reason....

    jc


  • Closed Accounts Posts: 1,322 ✭✭✭phobos


    Yeah bonkey I think we're on the same level here.

    Right I could do this on the client app:

    ResultSet rs = remoteBean.lookup("phobos");
    This would throw a casting exception, because a RJResultSet is being returned and I'm tring to assign it to a ResultSet

    RJResultSet rs = remoteBean.lookup("phobos");
    I couldn't do this because the client app cannot find a def for RJResultSet on my current classpath. For what reason I don't know.

    Object rs = (RJResultSet)remoteBean.lookup("phobos");
    Same as above

    I had a chat with the other admins on IJUG, and they pointed me to: http://www.objectweb.org/conference/RmiJdbc.pdf (it's a short PDF, with some interesting code listings)

    But the code seems to be using a different driver from what I'm using. Anyway it's from a client app, and not a bean. If I was to implement it I would have to go fuking around with the JDBC connectivity settings in my app server. I know I don't need to do this.

    ...?

    ;-phobos-)


  • Closed Accounts Posts: 37 nucular


    Okay,

    You probably have this working already but if not..

    The server app can see something that the client app can't therefore it is probably something to with the J2EE explicitly.

    I would try the following to get the client to compile and then if it works, work from there:

    javac -classpath "%classpath%;%J2EE_HOME%\lib\cloudscape\RmiJdbc.jar" yourapp.java

    This will work as long as the client can see the J2EE_HOME.

    good luck
    have to do some work now ;)


  • Closed Accounts Posts: 1,322 ✭✭✭phobos


    Nah I'm actually in the process of trying something else, because that was one of the strangest problems that I've ever seen. :confused:

    I know that the server can obviously see it because it;s able to use it, but the client however cannot. But the funny thing is that each console that I spawn both the J2EE server, and the client app, are using the exact same class path.

    They both contain a refference to %J2EE_HOME%\lib\cloudscape\RmiJdbc.jar

    So what's the fukking problem?? (I'm out of ideas). Unless the the container has it's own private stash of class definitions that it uses on the sly ;)

    ;-phobos-)


Advertisement