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 |