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 |
From: <php...@li...> - 2006-08-28 18:35:38
|
Hi, do you use the dynamic loader to load the classes? We've had two tickets with similar problems (class cast exception because the proxies were assignment incompatible to each other). Both of them were closed because the users provided no feedback. -- One user reported that the suggested workaround (to move the libraries to the global classpath) worked, after that he was unable to reproduce the original problem. However, I am quite sure there's still a bug in our dynamic loader when dynamic proxies are used. Can you please run the server with: -Dphp.java.bridge.default_log_file=/tmp/javabridge.log -Dphp.java.bridge.default_log_level=6 open a ticket (please use http://sourceforge.net/tracker/?func=add&group_id=117793&atid=679233) and attach the full log at the end of the ticket? The log file will be large, but it should contain information why our dynamic loader has dropped the proxy even though spring still keeps a reference to it. Thank you very much for the bug report! Regards, Jost Boekemeier ___________________________________________________________ Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de |
From: <php...@li...> - 2006-08-29 18:04:29
|
Ayer en la tarde, php...@li... dijo: > Hi, > > do you use the dynamic loader to load the classes? > > We've had two tickets with similar problems (class > cast exception because the proxies were assignment > incompatible to each other). Both of them were closed > because the users provided no feedback. -- One user > reported that the suggested workaround (to move the > libraries to the global classpath) worked, after that > he was unable to reproduce the original problem. > > However, I am quite sure there's still a bug in our > dynamic loader when dynamic proxies are used. Yes, as a matter of fact I load jar files on demand; this is the relevant part of the code (removed for brevity on previous post): ,---- | $cwd = dirname(__FILE__); | | $jars = array( | "$cwd/SpringDemo/", | "$cwd/jars/spring-aop.jar", | "$cwd/jars/spring-beans.jar", | "$cwd/jars/spring-context.jar", | "$cwd/jars/spring-core.jar", | "$cwd/jars/spring-dao.jar", | "$cwd/jars/spring.jar", | "$cwd/jars/spring-jdbc.jar", | "$cwd/jars/spring-remoting.jar", | "$cwd/jars/spring-web.jar", | "/home/staff/crgutier/jars/lib/j2ee/servlet-api.jar", | "$cwd/jars/lib/jakarta-commons/commons-logging.jar", | "$cwd/jars/lib/jakarta-commons/commons-httpclient.jar", | "$cwd/jars/lib/log4j/log4j-1.2.9.jar", | ); | | | java_require(join(";", $jars)); `---- I'll try with the workaround and report back. > Can you please run the server with: > > -Dphp.java.bridge.default_log_file=/tmp/javabridge.log > -Dphp.java.bridge.default_log_level=6 > > open a ticket (please use > http://sourceforge.net/tracker/?func=add&group_id=117793&atid=679233) > and attach the full log at the end of the ticket? > > The log file will be large, but it should contain > information why our dynamic loader has dropped the > proxy even though spring still keeps a reference to > it. Just did. Thanks for your help. -- Guti cat /dev/coffee | /dev/cup | /dev/mouth | /dev/nose > /dev/keyboard |
From: <php...@li...> - 2006-08-29 19:59:54
|
Hoy en la tarde, php...@li... dijo: > Ayer en la tarde, php...@li... dijo: >> Hi, >> >> do you use the dynamic loader to load the classes? >> >> We've had two tickets with similar problems (class >> cast exception because the proxies were assignment >> incompatible to each other). Both of them were closed >> because the users provided no feedback. -- One user >> reported that the suggested workaround (to move the >> libraries to the global classpath) worked, after that >> he was unable to reproduce the original problem. [...] > I'll try with the workaround and report back. No crahes after one hour of requests (w/ 1-minute delays). Seems pretty rock solid to me :) I'll go that route for now. Thanks! -- Guti Real Programmers don't comment their code. If it was hard to write, it should be hard to understand and even harder to modify. |