我可以遍历组件树,并查询和设置一些基本Java对象中的值,例如来自class oracle.forms.ui.VTextField的值
当我试图模拟用户点击oracle.apps.fnd.ui.Button时,我被卡住了
我试过2件事情:
>调用AbstractButton类的simulatePush方法
>调用PushButton类的activate方法
(2类在Button的类层次结构中)
结果相同:
首先,它工作正常:当按钮是“搜索”按钮时,搜索完成并显示结果.
然后,它立即中断应用程序,弹出一声说FRM-92100您与服务器的连接中断.
从那里,应用程序被挂起.
更新:
似乎导致与服务器断开连接的错误是:
java.lang.SecurityException: this KeyboardFocusManager is not
installed in the current thread’s context at
java.awt.KeyboardFocusManager.checkCurrentKFMSecurity(Unknown Source)
at java.awt.KeyboardFocusManager.getGlobalFocusOwner(Unknown Source)
at
java.awt.KeyboardFocusManager.processSynchronousLightweightTransfer(Unknown
Source) at
sun.awt.windows.WComponentPeer.processSynchronousLightweightTransfer(Native
Method) at sun.awt.windows.WComponentPeer.requestFocus(Unknown
Source) at java.awt.Component.requestFocusHelper(Unknown Source) at
java.awt.Component.requestFocusHelper(Unknown Source) at
java.awt.Component.requestFocus(Unknown Source) at
oracle.forms.handler.UICommon.updateFocus(Unknown Source) at
oracle.forms.handler.UICommon.setFVP(Unknown Source) at
oracle.forms.handler.UICommon.setFVP(Unknown Source) at
oracle.forms.handler.UICommon.onUpdate(Unknown Source) at
oracle.forms.handler.ComponentItem.onUpdate(Unknown Source) at
oracle.forms.handler.JavaContainer.onUpdate(Unknown Source) at
oracle.forms.handler.UICommon.onUpdate(Unknown Source) at
oracle.forms.engine.Runform.onUpdateHandler(Unknown Source) at
oracle.forms.engine.Runform.processMessage(Unknown Source) at
oracle.forms.engine.Runform.processSet(Unknown Source) at
oracle.forms.engine.Runform.onMessageReal(Unknown Source) at
oracle.forms.engine.Runform.onMessage(Unknown Source) at
oracle.forms.engine.Runform.processEventEnd(Unknown Source) at
oracle.ewt.lwAWT.LWComponent.redispatchEvent(Unknown Source) at
oracle.ewt.lwAWT.LWComponent.processEvent(Unknown Source) at
oracle.ewt.button.PushButton.activate(Unknown Source) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) at
CustomAWT.run(CustomAWT.java:34) at
java.awt.event.InvocationEvent.dispatch(Unknown Source) at
java.awt.EventQueue.dispatchEventImpl(Unknown Source) at
java.awt.EventQueue.access$400(Unknown Source) at
java.awt.EventQueue$2.run(Unknown Source) at
java.awt.EventQueue$2.run(Unknown Source) at
java.security.AccessController.doPrivileged(Native Method) at
java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown
Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown
Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at
java.awt.EventDispatchThread.run(Unknown Source)
我的代码在这里:CustomAWT.run(CustomAWT.java:34),并使用invokeLater调用.问题可能是:在调用oracle.ewt.button.PushButton.activate方法时,我不在正确的EDT.
在Java控制台中使用“列表线程”,我得到:
Dump thread list ... Group main,ac=30,agc=2,pri=10 main,5,alive traceMsgQueueThread,alive,daemon Timer-0,alive Java Plug-In Pipe Worker Thread (Client-Side),daemon AWT-Shutdown,alive AWT-Windows,6,daemon AWT-EventQueue-0,alive SysExecutionTheadCreator,daemon CacheMemoryCleanUpThread,daemon CacheCleanUpThread,daemon Browser Side Object Cleanup Thread,alive JVM[id=0]-Heartbeat,daemon Windows Tray Icon Thread,alive Thread-13,alive Group Plugin Thread Group,ac=3,agc=0,pri=10 AWT-EventQueue-1,alive TimerQueue,daemon ConsoleWriterThread,daemon Group http://xxxx.xxxx.xxxxx.xx:8001/OA_JAVA/-threadGroup,ac=13,pri=4 Applet 1 LiveConnect Worker Thread,4,alive AWT-EventQueue-2,alive thread applet-oracle/apps/fnd/formsClient/FormsLauncher.class-1,alive Applet 2 LiveConnect Worker Thread,alive thread applet-oracle.forms.engine.Main-2,alive Forms-StreamMessageReader,alive Forms-StreamMessageWriter,alive HeartBeat,alive Busy indicator,1,daemon TaskScheduler timer,alive CursorIdler,alive Thread-14,alive Flush Queue,alive Done.
所以,有三个AWT-EventQueue线程…问题现在:如何查询/检索正确的一个,以及如何使Runnable传递给invokeLater运行在“好线程”(我猜,好的是最后一个(AWT-EventQueue-2)
解决方法
我使用sun.awt.AppContext类.一些文档和来源here(grepcode.com)
>使用getAppContexts方法获取正在运行的AppContext的集合.
>对于每个检索的AppContext,使用getThreadGroup方法获取他的ThreadGroup.
>使用ThreadGroup对象,使用getName方法.
>当Thread组的名称以您的Forms Application的http:地址开头时,使用AppContext的get方法检索带有名称sun.awt.AppContext.EVENT_QUEUE_KEY的Object属性.
>检索到的对象是一个EventQueue.创建一个java.awt.event.InvocationEvent对象,将您的Runnable传递给CTOR,并使用EventQueue的postEvent方法.
>你的run方法将在正确的线程中执行.
备注:
>这个答案是一个具体的,适用于我,通过Internet Explorer链接启动的Oracle Forms应用程序的解决方案,并在java.exe进程中运行.在这种情况下,3个线程组如问题所示:main,Plugin Thread Group和http://xxxx.xxxx.xxxxx.xx:8001 / OA_JAVA / -threadGroup您的里程可能会有所不同.>如果不使用完全反射,而是导入sun.awt.AppContext,编译器可能会以警告形式发出警告:sun.awt.AppContext是Sun专有API,可能会在将来的版本中删除这不是很很酷,但我会和那个一起生活的,暂时的.>在run方法中,我使用oracle.ewt.lwAWT.AbstractButton的simulatePush方法测试了OK.>这里仿真的方法是invokeLater.对于invokeAndWait,postEvent调用需要更多的代码.查看EventQueue类的一些来源,作为起点.