|
From: <php...@li...> - 2006-08-28 03:10:45
|
Hello all,
First of all, thanks a lot for this amazing piece of work to everyone
involved. PHP on the frontend and Java in the backend is making a lot of
sense (a lot more than PHP-or-Java all the way 'round) over here :)
Now, my problem is the following: I have setup a Spring-based RMI
service, which works as expected the first times you try it from
PHP. After several times hitting the `refresh' button on the browser,
the proxy of the remote service "falls back" to the proxy factory
object.
My PHP code (without jar files and debug methods boilerplate):
,----
| $multService = null;
| try {
| $classpathResource = new Java("org.springframework.core.io.ClassPathResource",
| "beans.xml");
| $beanFactory = new Java("org.springframework.beans.factory.xml.XmlBeanFactory",
| $classpathResource);
|
| $multService = $beanFactory->getBean("multService");
|
| $xval = (int) rand(0,100);
| $yval = (int) rand(0,100);
|
| $x = new Java("java.lang.Integer", $xval);
| $y = new Java("java.lang.Integer", $yval);
|
| $ret = $multService->operate($x, $y);
|
| if ($ret == $xval * $yval)
| print "OK<br/>";
| else
| print "ERR<br/>";
|
| my_java_debug($multService);
| }
| catch(JavaException $ex)
| {
| my_java_print_stacktrace($ex);
| my_java_debug($multService);
| }
`----
When everything is ok, the output is:
,----
| OK
| <==== begin class debug ====>
| [class $Proxy1:
| Constructors:
| public $Proxy1(java.lang.reflect.InvocationHandler)
|
| Fields:
|
| Methods:
| public final java.lang.Integer $Proxy1.operate(java.lang.Integer,java.lang.Integer)
| public final void $Proxy1.addAdvice(int,org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException
| public final void $Proxy1.addAdvice(org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException
| public final void $Proxy1.setTargetSource(org.springframework.aop.TargetSource)
| public final org.springframework.aop.TargetSource $Proxy1.getTargetSource()
| public final java.lang.Class[] $Proxy1.getProxiedInterfaces()
| public final boolean $Proxy1.isInterfaceProxied(java.lang.Class)
| public final boolean $Proxy1.removeAdvice(org.aopalliance.aop.Advice) throws org.springframework.aop.framework.AopConfigException
| public final boolean $Proxy1.removeAdvisor(org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
| public final void $Proxy1.removeAdvisor(int) throws org.springframework.aop.framework.AopConfigException
| public final void $Proxy1.addAdvisor(org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
| public final void $Proxy1.addAdvisor(int,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
| public final org.springframework.aop.Advisor[] $Proxy1.getAdvisors()
| public final boolean $Proxy1.replaceAdvisor(org.springframework.aop.Advisor,org.springframework.aop.Advisor) throws org.springframework.aop.framework.AopConfigException
| public final java.lang.String $Proxy1.toProxyConfigString()
| public final boolean $Proxy1.isFrozen()
| public final void $Proxy1.setExposeProxy(boolean)
| public final boolean $Proxy1.isExposeProxy()
| public final boolean $Proxy1.isProxyTargetClass()
| public final int $Proxy1.hashCode()
| public final int $Proxy1.indexOf(org.springframework.aop.Advisor)
| public final boolean $Proxy1.equals(java.lang.Object)
| public final java.lang.String $Proxy1.toString()
| public static boolean java.lang.reflect.Proxy.isProxyClass(java.lang.Class)
| public static transient java.lang.Class java.lang.reflect.Proxy.getProxyClass(java.lang.ClassLoader,java.lang.Class[]) throws java.lang.IllegalArgumentException
| public static java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.getInvocationHandler(java.lang.Object) throws java.lang.IllegalArgumentException
| public static java.lang.Object java.lang.reflect.Proxy.newProxyInstance(java.lang.ClassLoader,java.lang.Class[],java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException
| public final native java.lang.Class java.lang.Object.getClass()
| public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
| public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
| public final void java.lang.Object.wait() throws java.lang.InterruptedException
| public final native void java.lang.Object.notify()
| public final native void java.lang.Object.notifyAll()
|
| Classes:
| ]
| <==== end class debug ====>
`----
And after a while it all goes *boink*:
,----
| <==== begin stack trace ====>
| java.lang.Exception: Invoke failed: [o(RmiProxyFactoryBean)]->operate(o(Integer), o(Integer)). Cause: java.lang.NoSuchMethodException: operate(o(Integer), o(Integer)). Candidates: [] Responsible VM: 1.5.0_06@http://java.sun.com/
| at php.java.bridge.JavaBridge.Invoke(JavaBridge.java:1055)
| at php.java.bridge.Request.handleRequest(Request.java:499)
| at php.java.bridge.Request.handleRequests(Request.java:544)
| at php.java.bridge.JavaBridge.run(JavaBridge.java:178)
| at php.java.bridge.BaseThreadPool$Delegate.run(BaseThreadPool.java:37)
| Caused by: java.lang.NoSuchMethodException: operate(o(Integer), o(Integer)). Candidates: []
| ... 5 more
|
| <==== end stack trace ====>
| <==== begin class debug ====>
| [class org.springframework.remoting.rmi.RmiProxyFactoryBean:
| Constructors:
| public org.springframework.remoting.rmi.RmiProxyFactoryBean()
|
| Fields:
|
| Methods:
| public boolean org.springframework.remoting.rmi.RmiProxyFactoryBean.isSingleton()
| public void org.springframework.remoting.rmi.RmiProxyFactoryBean.afterPropertiesSet() throws java.lang.Exception
| public java.lang.Class org.springframework.remoting.rmi.RmiProxyFactoryBean.getObjectType()
| public java.lang.Object org.springframework.remoting.rmi.RmiProxyFactoryBean.getObject()
| public void org.springframework.remoting.rmi.RmiClientInterceptor.setLookupStubOnStartup(boolean)
| public void org.springframework.remoting.rmi.RmiClientInterceptor.setCacheStub(boolean)
| public void org.springframework.remoting.rmi.RmiClientInterceptor.setRefreshStubOnConnectFailure(boolean)
| public java.lang.Object org.springframework.remoting.rmi.RmiClientInterceptor.invoke(org.aopalliance.intercept.MethodInvocation) throws java.lang.Throwable
| public void org.springframework.remoting.rmi.RmiClientInterceptor.prepare() throws java.lang.Exception
| public void org.springframework.remoting.support.RemoteInvocationBasedAccessor.setRemoteInvocationFactory(org.springframework.remoting.support.RemoteInvocationFactory)
| public org.springframework.remoting.support.RemoteInvocationFactory org.springframework.remoting.support.RemoteInvocationBasedAccessor.getRemoteInvocationFactory()
| public java.lang.String org.springframework.remoting.support.UrlBasedRemoteAccessor.getServiceUrl()
| public void org.springframework.remoting.support.UrlBasedRemoteAccessor.setServiceUrl(java.lang.String)
| public java.lang.Class org.springframework.remoting.support.RemoteAccessor.getServiceInterface()
| public void org.springframework.remoting.support.RemoteAccessor.setServiceInterface(java.lang.Class)
| public native int java.lang.Object.hashCode()
| public final native java.lang.Class java.lang.Object.getClass()
| public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
| public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
| public final void java.lang.Object.wait() throws java.lang.InterruptedException
| public boolean java.lang.Object.equals(java.lang.Object)
| public final native void java.lang.Object.notify()
| public final native void java.lang.Object.notifyAll()
| public java.lang.String java.lang.Object.toString()
|
| Classes:
| ]
| <==== end class debug ====>
`----
(Note that the dumped classes are not the same in both outputs)
Some things I observed:
* When it's still good, proxy instances are numbered $Proxy0, $Proxy1,
... etc., but the number doesn't change if there is a small time lapse
between requests (a few seconds). I guess that's a normal behaviour,
anyway.
* Given that the InvocationHandler object starts being replaced by a
RmiProxyFactoryBean object, I tried to consecutively call
$multService->getBean("multService") until I got the object I was
waiting for (just in case some weird bug in Spring could be returning
"this" from inside the Factory). It worked for a few tries, and then I
got a null object and couldn't go forward.
* I tried with various RMI-recovering options for Spring's remote
factory (cacheStub, refreshStubOnConnectFailure and
lookupStubOnStartup), but to no avail.
* A restart of the web server solves (if we can call that a "solution")
the problem.
* I couldn't find a pattern that would predict when RMI would fail. I
thought that perhaps a run of System.gc() could trigger it, but a line
like this didn't:
$sys = new Java("java.lang.System"); $sys->gc();
These are the gory details:
* Web server is Apache 2.0 w/PHP 5.1.4 from Debian Sarge backports.
* JVM is 1.5.0_06 from Sun.
* PHP-Java Bridge is 3.1.7 (for FC4).
Thanks in advance for any insights.
--
Guti
Chuck Norris dont need to catch an Exception because Java is afraid of
the "flying tornado kick" at the moment it throws
|