I saw a bug when using DWR 2 in an OSGI environment. It occurs when trying to directly expose an OSGi service configured with Spring DM as a DWR remote service like below. I don't have the problem when defining an intermediate class between dwr and the OSGi service referenced using Spring DM.
I have the following error when calling a method on the service with DWR:
10108 [http-8080-Processor4] WARN org.directwebremoting.impl.DefaultRemoter - Method execution failed:
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.directwebremoting.impl.ExecuteAjaxFilter.doFilter(ExecuteAjaxFilter.java:36)
at org.directwebremoting.impl.DefaultRemoter$1.doFilter(DefaultRemoter.java:434)
at org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:437)
at org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:283)
(...)
The problem comes from the BeanCreator class when determining type of the bean corresponding to the call. Spring DM provides a proxy in front of the OSGi service. The method afterPropertiesSet of the BeanCreator class sets this type with the implementation class instead of the proxy class...
To fix this bug, we can get this type directly using the proxy instance as shown below:
public void afterPropertiesSet()
{
// make sure that either the bean or the beanId have been set correctly
if (bean != null) {
this.beanClass = bean.getClass();
} else if (beanId != null) {
//this.beanClass = beanFactory.getType(beanId);
this.beanClass = beanFactory.getBean(beanId).getClass(); <----------------
} else {
throw new FatalBeanException(
"You should either set the bean property directly or set the beanId property");
}
// make sure to handle cglib proxies correctly
if(AopUtils.isCglibProxyClass(this.beanClass)) {
this.beanClass = this.beanClass.getSuperclass();
}
}
Hello,
I saw a bug when using DWR 2 in an OSGI environment. It occurs when trying to directly expose an OSGi service configured with Spring DM as a DWR remote service like below. I don't have the problem when defining an intermediate class between dwr and the OSGi service referenced using Spring DM.
<dwr:configuration>
<dwr:create javascript="contactService" type="spring">
<dwr:param name="beanName" value="contactService"/>
<dwr:convert type="bean" class="com.manning.sdmia.directory.model.Contact"/>
</dwr:create>
</dwr:configuration>
<dwr:controller id="dwrController" debug="true"/>
<osgi:reference id="contactService"
interface="com.manning.sdmia.directory.service.ContactService">
</osgi:reference>
I have the following error when calling a method on the service with DWR:
10108 [http-8080-Processor4] WARN org.directwebremoting.impl.DefaultRemoter - Method execution failed:
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.directwebremoting.impl.ExecuteAjaxFilter.doFilter(ExecuteAjaxFilter.java:36)
at org.directwebremoting.impl.DefaultRemoter$1.doFilter(DefaultRemoter.java:434)
at org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:437)
at org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:283)
(...)
The problem comes from the BeanCreator class when determining type of the bean corresponding to the call. Spring DM provides a proxy in front of the OSGi service. The method afterPropertiesSet of the BeanCreator class sets this type with the implementation class instead of the proxy class...
To fix this bug, we can get this type directly using the proxy instance as shown below:
public void afterPropertiesSet()
{
// make sure that either the bean or the beanId have been set correctly
if (bean != null) {
this.beanClass = bean.getClass();
} else if (beanId != null) {
//this.beanClass = beanFactory.getType(beanId);
this.beanClass = beanFactory.getBean(beanId).getClass(); <----------------
} else {
throw new FatalBeanException(
"You should either set the bean property directly or set the beanId property");
}
// make sure to handle cglib proxies correctly
if(AopUtils.isCglibProxyClass(this.beanClass)) {
this.beanClass = this.beanClass.getSuperclass();
}
}
Thierry
What's the actual class returned by getType() and by getBean().getClass() in this situation? The docs seem to imply that the result of both calls should be equal
Jose Noheda added a comment - 04/Nov/09 6:31 AM What's the actual class returned by getType() and by getBean().getClass() in this situation? The docs seem to imply that the result of both calls should be equal
It's very strange and it seems to be a bug of Spring...
If I add traces in the BeanCreator to get these informations, I have two different proxy instances:
beanFactory.getType(beanId) = class $Proxy3
beanFactory.getBean(beanId).getClass() = class $Proxy4
Feel free to tell if you want my complete workspace to make tests!
Thierry Templier added a comment - 05/Nov/09 12:31 AM Hello,
It's very strange and it seems to be a bug of Spring...
If I add traces in the BeanCreator to get these informations, I have two different proxy instances:
beanFactory.getType(beanId) = class $Proxy3
beanFactory.getBean(beanId).getClass() = class $Proxy4
Feel free to tell if you want my complete workspace to make tests!
Thierry