Defect #177
Jasper viewer fails in webclient
0%
Description
My Jasper viewer fails in webclient. There is a popup window for a second, but that popup disappears very fast.
I tested also with a small report (almost empty report), so it doesn't seem to be the report.
It happens for all my reports. It happens also on both IE8 and FF 3.6
In smartclient the Jasper viewer is shown correctly. Also running this report from iReports 3.7.1 no problem or any errormessage.
In the Servoy log I see the following error:
2010-10-20 12:59 http-8080-7 ERROR com.servoy.j2db.util.Debug Throwable
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at com.servoy.j2db.scripting.ScriptEngine.registerScriptObjectReturnTypes(ScriptEngine.java:144)
at com.servoy.j2db.scripting.PluginScope.get(PluginScope.java:42)
at org.mozilla.javascript.ScriptableObject.getProperty(ScriptableObject.java:1641)
at org.mozilla.javascript.ScriptRuntime.getObjectProp(ScriptRuntime.java:1429)
at org.mozilla.javascript.ScriptRuntime.getObjectProp(ScriptRuntime.java:1418)
at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:3343)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2680)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:166)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:387)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3125)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:165)
at com.servoy.j2db.scripting.ScriptEngine.executeFunction(ScriptEngine.java:42)
at com.servoy.j2db.scripting.ScriptEngine.executeFunction(ScriptEngine.java:143)
at com.servoy.j2db.FormController.Za(FormController.java:1078)
at com.servoy.j2db.FormController.executeFunction(FormController.java:439)
at com.servoy.j2db.Zhb.Za(Zhb.java:5)
at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor.fireActionCommand(WebEventExecutor.java:83)
at com.servoy.j2db.server.headlessclient.dataui.WebEventExecutor.onEvent(WebEventExecutor.java:52)
at com.servoy.j2db.server.headlessclient.dataui.Zjc.onEvent(Zjc.java:2)
at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:163)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:297)
at org.apache.wicket.request.target.component.listener.BehaviorRequestTarget.processEvents(BehaviorRequestTarget.java:104)
at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:91)
at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1248)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1325)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1427)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:532)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:356)
at com.servoy.j2db.server.servlets.Zi.doGet(Zi.java:6)
at org.apache.wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:124)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source)
Files
History
Updated by Rob Gansevles over 14 years ago
Martin,
Which version of Servoy is this?
Please add the full stack trace, I expect there is also a caused-by part.
Can you also test with all non-servoy plugins (except for the jasper reports plugin) removed from the plugins folder?
Rob
Updated by Martin Heere over 14 years ago
Rob,
With minimum plugins same behavior. There are no more messages than I gave before.
It happens with both Servoy 4.1.6 and 5.1.4 and 5.2.2
I tried the Plugin 3.1 as well as the most recent update (4)
When trace on I see the following in the trace concerning the plugin:
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: JasperReport finished
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperDebug: Parameter: salesorder_id (java.lang.String): a9ba3759-7401-4e2d-9d96-253b5ce9599c
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperDebug: Parameter: company_id (java.lang.Integer): 28
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: Extra Directories: null
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: Directory: \\Servoy\Globis Online\Reports
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: Directory: \\Servoy\Globis Online\Reports
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: Directory: \\Servoy\Globis Online\Reports
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: getconnection for: gede_online
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: JasperReport service found
2010-10-20 14:45 http-8080-3 INFO com.servoy.j2db.util.Debug JasperTrace: JasperReport initialize
The database server exists and also the directory exists. Other databases and directies give the same problem.
If you wanted to see a dump of the stack, it is here:
Current time: Wed Oct 20 14:22:57 CEST 2010
Server Information
Servoy version 4.1.6 -build 689
Repository version 35
Uptime: 1 minute 33 seconds
JDK Information
java.vm.name=Java HotSpot(TM) Client VM
java.version=1.6.0_21-b07
java.vm.info=mixed mode, sharing
java.vm.vendor=Sun Microsystems Inc.
Operating System Information
os.name=Windows 2003
os.version=5.2
os.arch=x86
System Information
Heap memory: allocated=148292K, used=97939K, max=506816K
None Heap memory: allocated=63840K, used=53313K, max=317440K
Thread: http-8080-3, state: RUNNABLE, total cpu time: 1000.0ms, total user time: 984.375ms
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(Unknown Source)
org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:700)
org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:366)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:805)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Unknown Source)
Thread: http-8080-2, state: RUNNABLE, total cpu time: 78.125ms, total user time: 78.125ms
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(Unknown Source)
org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:700)
org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:366)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:805)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Unknown Source)
Thread: FormCache Monitor, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Thread.sleep(Native Method)
com.servoy.j2db.server.headlessclient.dataui.Zl.run(Zl.java:2)
java.lang.Thread.run(Unknown Source)
Thread: AWT-Windows, state: RUNNABLE, total cpu time: 0.0ms, total user time: 0.0ms
sun.awt.windows.WToolkit.eventLoop(Native Method)
sun.awt.windows.WToolkit.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Thread: Java2D Disposer, state: WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(Unknown Source)
java.lang.ref.ReferenceQueue.remove(Unknown Source)
sun.java2d.Disposer.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Thread: ModificationWatcher Task, state: TIMED_WAITING, total cpu time: 15.625ms, total user time: 0.0ms
java.lang.Thread.sleep(Native Method)
org.apache.wicket.util.time.Duration.sleep(Duration.java:446)
org.apache.wicket.util.thread.Task$1.run(Task.java:130)
java.lang.Thread.run(Unknown Source)
Thread: http-8080-1, state: RUNNABLE, total cpu time: 3906.25ms, total user time: 3812.5ms
sun.management.ThreadImpl.getThreadInfo0(Native Method)
sun.management.ThreadImpl.getThreadInfo(Unknown Source)
sun.management.ThreadImpl.getThreadInfo(Unknown Source)
com.servoy.j2db.server.servlets.ConfigServlet.Zt(ConfigServlet.java:1599)
com.servoy.j2db.server.servlets.ConfigServlet.service(ConfigServlet.java:3188)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
java.lang.Thread.run(Unknown Source)
Thread: DestroyJavaVM, state: RUNNABLE, total cpu time: 4828.125ms, total user time: 4484.375ms
Thread: http-8080-Acceptor-0, state: RUNNABLE, total cpu time: 0.0ms, total user time: 0.0ms
java.net.PlainSocketImpl.socketAccept(Native Method)
java.net.PlainSocketImpl.accept(Unknown Source)
java.net.ServerSocket.implAccept(Unknown Source)
java.net.ServerSocket.accept(Unknown Source)
org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:61)
org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:310)
java.lang.Thread.run(Unknown Source)
Thread: ContainerBackgroundProcessor[StandardEngine[Catalina]], state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Thread.sleep(Native Method)
org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1579)
java.lang.Thread.run(Unknown Source)
Thread: Timer-1, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
java.util.TimerThread.mainLoop(Unknown Source)
java.util.TimerThread.run(Unknown Source)
Thread: ClientExportNotifyListner0, state: RUNNABLE, total cpu time: 0.0ms, total user time: 0.0ms
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(Unknown Source)
java.io.BufferedInputStream.fill(Unknown Source)
java.io.BufferedInputStream.read(Unknown Source)
com.servoy.j2db.util.rmi.compressing.Zc.Za(Zc.java:71)
com.servoy.j2db.util.rmi.compressing.Zc.read(Zc.java:11)
java.io.DataInputStream.readInt(Unknown Source)
com.servoy.j2db.util.rmi.Zi.run(Zi.java:6)
Thread: SocketAccepter0, state: WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
com.servoy.j2db.util.TaskExecuter.run(TaskExecuter.java:29)
java.lang.Thread.run(Unknown Source)
Thread: pool-2-thread-1, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
java.util.concurrent.DelayQueue.take(Unknown Source)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Thread: GC Daemon, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
sun.misc.GC$Daemon.run(Unknown Source)
Thread: RMI Reaper, state: WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(Unknown Source)
java.lang.ref.ReferenceQueue.remove(Unknown Source)
sun.rmi.transport.ObjectTable$Reaper.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Thread: TaskExecuter0, state: RUNNABLE, total cpu time: 921.875ms, total user time: 843.75ms
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(Unknown Source)
java.io.DataInputStream.readFully(Unknown Source)
java.io.DataInputStream.readFully(Unknown Source)
net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:814)
net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:695)
net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:443)
net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:102)
net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:87)
net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:3772)
net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1031)
net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:360)
net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:672)
sun.reflect.GeneratedMethodAccessor58.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
com.servoy.j2db.persistence.datasource.Ze.invoke(Ze.java:10)
$Proxy0.executeQuery(Unknown Source)
org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:179)
org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:179)
org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:179)
com.servoy.j2db.persistence.Zuc.Zc(Zuc.java:265)
com.servoy.j2db.persistence.Server.reloadTableColumnInfo(Server.java:661)
com.servoy.j2db.persistence.Server.initTable(Server.java:911)
com.servoy.j2db.persistence.Server.initTableIfNecessary(Server.java:324)
com.servoy.j2db.persistence.Server.getTable(Server.java:455)
com.servoy.j2db.server.Zf.run(Zf.java:30)
com.servoy.j2db.util.TaskExecuter.run(TaskExecuter.java:26)
java.lang.Thread.run(Unknown Source)
Thread: RMI TCP Accept-1099, state: WAITING, total cpu time: 0.0ms, total user time: 0.0ms
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(Unknown Source)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
java.util.concurrent.ArrayBlockingQueue.take(Unknown Source)
com.servoy.j2db.util.rmi.Zl.accept(Zl.java:77)
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(Unknown Source)
sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Thread: 2 way Server Acceptor, state: RUNNABLE, total cpu time: 0.0ms, total user time: 0.0ms
java.net.PlainSocketImpl.socketAccept(Native Method)
java.net.PlainSocketImpl.accept(Unknown Source)
java.net.ServerSocket.implAccept(Unknown Source)
com.servoy.j2db.util.rmi.Zl.run(Zl.java:28)
java.lang.Thread.run(Unknown Source)
Thread: pool-1-thread-1, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
java.util.concurrent.DelayQueue.take(Unknown Source)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Thread: PingScanner, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
com.servoy.j2db.dataprocessing.Zx.run(Zx.java:19)
java.lang.Thread.run(Unknown Source)
Thread: MessageScheduler, state: TIMED_WAITING, total cpu time: 0.0ms, total user time: 0.0ms
java.lang.Object.wait(Native Method)
com.servoy.j2db.dataprocessing.Zz.run(Zz.java:39)
java.lang.Thread.run(Unknown Source)
Thread: Attach Listener, state: RUNNABLE, total cpu time: 0.0ms, total user time: 0.0ms
Thread: Signal Dispatcher, state: RUNNABLE, total cpu time: 0.0ms, total user time: 0.0ms
Thread: Finalizer, state: WAITING, total cpu time: 15.625ms, total user time: 15.625ms
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(Unknown Source)
java.lang.ref.ReferenceQueue.remove(Unknown Source)
java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
Thread: Reference Handler, state: WAITING, total cpu time: 31.25ms, total user time: 31.25ms
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
Updated by Martin Heere over 14 years ago
More info:
The report is actually created and I find it in my Downloads directory as a pdf-file.
But for some reason the pdf-file is not opened by the browser.
I guess the new Instance() error is coming from creating a new instance of the browser, which is necessary to open the pdf.
On my computer there are several browsers installed (IE8, FF, Chrome). Could that be a reason?
Updated by Jeff Bader about 14 years ago
Unfortunately the Jasper plugin's pushing of files via webclient doesn't work as well as the file plugin does (they should be merged actually, meaning the Jasper plugin should probably use the same mechanism as the file plugin, which is now really pretty excellent thanks to Patrick's work). I guess that the mechanisms for pushing the file are different, but have not looked. I have the same behavior, and probably everyone who uses the plugin has the same behavior - meaning empty blank windows, or no blank windows, and problems with IE. I'm surprised though that you are able to get the reports downloaded at all though in IE. I have never been able to use IE with our WC system for the sole reason that I can't make reports created with the Jasper plugin push the rendered reports via WC. There is actually a long-standing issue on this at the old google code site.
I can't explain your exception per se, but I can tell you that the pushing of files via WC using the Jasper plugin's implementation isn't good.
I'm actively in the process of paying for development on this plugin, to fix this and other issues. FYI. When I do, I will discuss all of that work with Servoy and see how it might be contributed.
Updated by Patrick Talbot about 14 years ago
- File servoy_jasperreports.patch added
Please find attached a patch to fix this issue.
There's only one line changed in the JasperReportsWebViewer class at line 68:
Using showURL(url, "_self", null) instead of showURL(url, '_blank', null) works for all modern browsers, this is what is used successfully by the file plugin in the same situation.
Tested on Windows XP and 7 with IE 7/8 - Firefox 3.6 - Chrome 8 and on Mac OS X with Safari 5 - Firefox 3.6
Also note: for people using IE 8 and trying to output excel files in their web browser, use OUTPUT_FORMAT.XLS instead of OUTPUT_FORMAT.EXCEL otherwise the file will be named *.excel and IE 8 will be confused even if the mime-type is set correctly, OUTPUT_FORMAT.XLS set the extension to xls and IE 8 is happy.
Updated by Patrick Talbot about 14 years ago
The previous patch add my changes of servoy.properties
This one only contains the change of the JasperReportsWebViewer class.
Updated by Rob Gansevles about 14 years ago
- Status changed from New to Closed
- Assignee set to Rob Gansevles
Applied Patrick's patch.
Thanks,
Rob