[
https://issues.jboss.org/browse/JBAS-2473?page=com.atlassian.jira.plugin....
]
Leonardo Mendoza commented on JBAS-2473:
----------------------------------------
I would like to re-open this issue.
In my testing of JBoss 4.0.4.GA, 5.1.0.GA, and 6.1.0.Final I've always encountered
ClassCastExceptions when DatabaseMetaData methods that return ResultSets are called.
According to this post on the ~StackOverflow website: [Java.lang.reflect.Proxy returning
another proxy from invocation results in ClassCastException on assignment |
http://stackoverflow.com/questions/2642700/java-lang-reflect-proxy-return...],
the method that retrieves all interfaces implemented by the provided class needs to use a
transitive closure to properly get the interfaces.
The {{org.jboss.util.Classes.getAllInterfaces(Class)}} needs to change so that it properly
retrieves all implemented interfaces:
{code:title=org.jboss.util.Classes - current implementation}
/**
* Populates a list with all the interfaces implemented by the argument
* class c and all its superclasses.
*
* @param allIfaces - the list to populate with the interfaces
* @param c - the class to start scanning for interfaces
*/
public static void getAllInterfaces(List allIfaces, Class c)
{
while (c != null)
{
Class[] ifaces = c.getInterfaces();
for (int n = 0; n < ifaces.length; n ++)
{
allIfaces.add(ifaces[n]);
}
c = c.getSuperclass();
}
}
{code}
{code:title=org.jboss.util.Classes - FIXED implementation}
/**
* Populates a list with all the interfaces implemented by the argument
* class c and all its superclasses.
*
* @param allIfaces - the list to populate with the interfaces
* @param c - the class to start scanning for interfaces
*/
public static void getAllInterfaces(List allIfaces, Class c)
{
allIfaces.addAll(getInterfaces(c));
}
/**
* Correctly gets all interfaces implemented by the given class.
* {@code Class.getInterfaces()} returns only the interfaces DIRECTLY
* implemented by the class. You need a transitive closure to obtain all the
* interfaces.
* Solution taken from
http://stackoverflow.com/questions/2642700/java-lang-reflect-proxy-return...
* @param clazz the class to get all the interfaces from.
* @return all interfaces implemented by {@code clazz} and its superclasses.
*/
private static List<Class<?>> getInterfaces(Class<?> clazz) {
List<Class<?>> interfaces = new ArrayList<Class<?>>();
if (clazz.isInterface()) {
interfaces.add(clazz);
} else {
do {
addInterfaces(clazz, interfaces);
clazz = clazz.getSuperclass();
} while (clazz != null);
}
for (int i = 0; i < interfaces.size(); ++i) {
addInterfaces(interfaces.get(i), interfaces);
}
return interfaces;
}
/**
* Helper method used by {@code getInterfaces(...)} for getting all the
* interfaces implemented by {@code clazz} and its superclasses.
* @param clazz the class to get all the interfaces from.
* @param interfaces the {@code List} of interfaces implemented by
* {@code clazz} and its parent classes.
*/
private static void addInterfaces(Class<?> clazz, List<Class<?>>
interfaces) {
for (Class<?> intf : clazz.getInterfaces()) {
if (!interfaces.contains(intf)) {
interfaces.add(intf);
}
}
}
{code}
I have tested this code on 5.1.0.GA and it works without issue.
Remote side ClassCastExceptions as a result of
WrapperDataSourceService using "getInterfaces()" to create Proxies.
------------------------------------------------------------------------------------------------------------------
Key: JBAS-2473
URL:
https://issues.jboss.org/browse/JBAS-2473
Project: Application Server 3 4 5 and 6
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: Remoting
Affects Versions: JBossAS-4.0.3 SP1
Environment: Windows XP, jdk1.5.0_05
Reporter: J Barkanic
Fix For: JBossAS-4.0.4.CR2, JBossAS-5.0.0.Beta1
The methods, createStatementProxy and createResultSetProxy in WrapperDataSourceService
use Object.getClass().getInterfaces() to gather interface information in order to create
proxies to the database driver Statement and ResultSet objects. However, if the
underlying driver implementation objects inherit their interfaces from a superclass,
"getInterfaces()" will not return those interfaces. (Derby Embedded driver does
this for ResultSet) This causes a ClassCastException on the remote side.
Other methods like createDatabaseMetaData just set the java.sql interface explicitly when
creating the proxy. (I don't know if there was a reason not to do this in these two
methods).
public interface MyInterface{
public void interfaceMethod();
}
public abstract class MyObjectA implements MyInterface{
public void interfaceMethod(){
//Implement interface
}
}
public class MyObjectB extends MyObjectA{
public void interfaceMethod(){
//Overridden implementation
}
}
public class Tester{
public static void main(String[] args){
MyObjectB b = new MyObjectB();
Class[] ifaces = b.getClass().getInterfaces(); //<----------- This will not
contain MyInterface
}
}
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see:
http://www.atlassian.com/software/jira