@@ -135,10 +135,17 @@ public void run() {
135135 */
136136 public static SWTBotMenu getDebuggerConnectMenuForDebugObject (Object debugObject ) {
137137 openDebugPerspective ();
138- Object windowMenu = findGlobal ("Window" , Option .factory ().widgetClass (MenuItem .class ).build ());
139- goMenuItem (windowMenu , "Show View" , "Debug" );
138+ // Open Debug view using Eclipse API instead of menu navigation
139+ // This is more reliable in headless CI environments
140+ showDebugView ();
140141
141142 SWTBotTreeItem obj = new SWTBotTreeItem ((TreeItem ) debugObject );
143+
144+ // Ensure the tree item is properly selected and focused before accessing context menu
145+ // This is critical for headless CI environments where context menus can hang
146+ obj .select ();
147+ obj .setFocus ();
148+ MagicWidgetFinder .pause (500 );
142149
143150 return obj .contextMenu ("Connect Liberty Debugger" );
144151 }
@@ -152,8 +159,15 @@ public static SWTBotMenu getDebuggerConnectMenuForDebugObject(Object debugObject
152159 */
153160 public static void disconnectDebugTarget (Object debugTarget ) {
154161 openDebugPerspective ();
155- Object windowMenu = findGlobal ("Window" , Option .factory ().widgetClass (MenuItem .class ).build ());
156- goMenuItem (windowMenu , "Show View" , "Debug" );
162+ // Open Debug view using Eclipse API instead of menu navigation
163+ // This is more reliable in headless CI environments
164+ showDebugView ();
165+
166+ // Ensure proper selection before accessing context menu
167+ SWTBotTreeItem obj = new SWTBotTreeItem ((TreeItem ) debugTarget );
168+ obj .select ();
169+ obj .setFocus ();
170+ MagicWidgetFinder .pause (500 );
157171
158172 MagicWidgetFinder .context (debugTarget , "Disconnect" );
159173
@@ -164,34 +178,30 @@ public static void disconnectDebugTarget(Object debugTarget) {
164178 * Terminate the launch
165179 */
166180 public static void terminateLaunch () {
167- Display .getDefault ().syncExec (new Runnable () {
168- @ Override
169- public void run () {
170- openDebugPerspective ();
171- Object windowMenu = findGlobal ("Window" , Option .factory ().widgetClass (MenuItem .class ).build ());
172- goMenuItem (windowMenu , "Show View" , "Debug" );
181+ // Don't wrap in syncExec - MagicWidgetFinder methods already handle thread synchronization
182+ // Nested syncExec calls can cause deadlocks in headless CI environments
183+ openDebugPerspective ();
184+ showDebugView ();
173185
174- Object debugView = MagicWidgetFinder .findGlobal ("Debug" );
186+ Object debugView = MagicWidgetFinder .findGlobal ("Debug" );
175187
176- Object launch = MagicWidgetFinder .find ("[Liberty]" , debugView ,
177- Option .factory ().useContains (true ).setThrowExceptionOnNotFound (false ).build ());
188+ Object launch = MagicWidgetFinder .find ("[Liberty]" , debugView ,
189+ Option .factory ().useContains (true ).setThrowExceptionOnNotFound (false ).build ());
178190
179- // Only attempt to terminate if launch exists
180- if (launch != null ) {
181- MagicWidgetFinder .context (launch , "Terminate and Remove" );
191+ // Only attempt to terminate if launch exists
192+ if (launch != null ) {
193+ MagicWidgetFinder .context (launch , "Terminate and Remove" );
182194
183- try {
184- Shell confirm = (Shell ) findGlobal ("Terminate and Remove" , Option .factory ().widgetClass (Shell .class ).build ());
195+ try {
196+ Shell confirm = (Shell ) findGlobal ("Terminate and Remove" , Option .factory ().widgetClass (Shell .class ).build ());
185197
186- MagicWidgetFinder .go ("Yes" , confirm );
187- MagicWidgetFinder .pause (3000 );
188- } catch (Exception e ) {
189- // The configrmation pop up window only shows if the launch has not yet been terminated.
190- // If it has been terminated (or stopped), there is no confirmation.
191- }
192- }
198+ MagicWidgetFinder .go ("Yes" , confirm );
199+ MagicWidgetFinder .pause (3000 );
200+ } catch (Exception e ) {
201+ // The configrmation pop up window only shows if the launch has not yet been terminated.
202+ // If it has been terminated (or stopped), there is no confirmation.
193203 }
194- });
204+ }
195205 }
196206
197207 /**
@@ -203,21 +213,37 @@ public void run() {
203213 * @return
204214 */
205215 public static Object getObjectInDebugView (final String objectName ) {
206- final Object [] result = new Object [1 ];
207- Display .getDefault ().syncExec (new Runnable () {
208- @ Override
209- public void run () {
210- openDebugPerspective ();
211- Object windowMenu = findGlobal ("Window" , Option .factory ().widgetClass (MenuItem .class ).build ());
212- goMenuItem (windowMenu , "Show View" , "Debug" );
216+ // Don't wrap in syncExec - MagicWidgetFinder methods already handle thread synchronization
217+ // Nested syncExec calls can cause deadlocks in headless CI environments
218+ openDebugPerspective ();
219+ showDebugView ();
213220
214- Object debugView = MagicWidgetFinder .findGlobal ("Debug" );
221+ Object debugView = MagicWidgetFinder .findGlobal ("Debug" );
215222
216- result [0 ] = MagicWidgetFinder .find (objectName , debugView ,
217- Option .factory ().useContains (true ).setThrowExceptionOnNotFound (false ).widgetClass (TreeItem .class ).build ());
218- }
219- });
220- return result [0 ];
223+ // Explicitly activate the Debug view to ensure widgets are properly rendered
224+ // This is critical for headless CI environments
225+ if (debugView instanceof ViewPart ) {
226+ final ViewPart vp = (ViewPart ) debugView ;
227+ Display .getDefault ().syncExec (new Runnable () {
228+ @ Override
229+ public void run () {
230+ try {
231+ IWorkbench wb = PlatformUI .getWorkbench ();
232+ IWorkbenchWindow window = wb .getActiveWorkbenchWindow ();
233+ if (window != null && window .getActivePage () != null ) {
234+ window .getActivePage ().activate (vp );
235+ }
236+ } catch (Exception e ) {
237+ System .err .println ("Failed to activate Debug view: " + e .getMessage ());
238+ }
239+ }
240+ });
241+ // Give the view time to activate
242+ MagicWidgetFinder .pause (500 );
243+ }
244+
245+ return MagicWidgetFinder .find (objectName , debugView ,
246+ Option .factory ().useContains (true ).setThrowExceptionOnNotFound (false ).widgetClass (TreeItem .class ).build ());
221247 }
222248
223249 /**
@@ -240,6 +266,31 @@ public void run() {
240266 Display .getDefault ().syncExec (runnable );
241267 }
242268
269+ /**
270+ * Opens the Debug view using Eclipse API directly.
271+ * This is more reliable than menu navigation in headless CI environments.
272+ */
273+ private static void showDebugView () {
274+ Display .getDefault ().syncExec (new Runnable () {
275+ @ Override
276+ public void run () {
277+ try {
278+ IWorkbench wb = PlatformUI .getWorkbench ();
279+ IWorkbenchWindow window = wb .getActiveWorkbenchWindow ();
280+ if (window != null && window .getActivePage () != null ) {
281+ // Show the Debug view using its ID
282+ window .getActivePage ().showView ("org.eclipse.debug.ui.DebugView" );
283+ }
284+ } catch (Exception e ) {
285+ System .err .println ("Failed to open Debug view: " + e .getMessage ());
286+ e .printStackTrace ();
287+ }
288+ }
289+ });
290+ // Give the view time to open
291+ MagicWidgetFinder .pause (500 );
292+ }
293+
243294 public static void openJavaPerspectiveViaMenu () {
244295 Object windowMenu = findGlobal ("Window" , Option .factory ().widgetClass (MenuItem .class ).build ());
245296
@@ -723,8 +774,9 @@ public static void checkRunCleanProjectCheckBox(Shell shell, String runDebugConf
723774
724775 public static Object getAppInPackageExplorerTree (String appName ) {
725776 openJavaPerspectiveViaMenu ();
726- Object windowMenu = findGlobal ("Window" , Option .factory ().widgetClass (MenuItem .class ).build ());
727- goMenuItem (windowMenu , "Show View" , "Package Explorer" );
777+ // Open Package Explorer view using Eclipse API instead of menu navigation
778+ // This is more reliable in headless CI environments
779+ showPackageExplorerView ();
728780 Object peView = MagicWidgetFinder .findGlobal ("Package Explorer" );
729781
730782 Object project = MagicWidgetFinder .find (appName , peView , Option .factory ().useContains (true ).widgetClass (TreeItem .class ).build ());
@@ -988,6 +1040,31 @@ public static void closeDashboardView(SWTWorkbenchBot bot) {
9881040 }
9891041 }
9901042
1043+ /**
1044+ * Opens the Package Explorer view using Eclipse API directly.
1045+ * This is more reliable than menu navigation in headless CI environments.
1046+ */
1047+ private static void showPackageExplorerView () {
1048+ Display .getDefault ().syncExec (new Runnable () {
1049+ @ Override
1050+ public void run () {
1051+ try {
1052+ IWorkbench wb = PlatformUI .getWorkbench ();
1053+ IWorkbenchWindow window = wb .getActiveWorkbenchWindow ();
1054+ if (window != null && window .getActivePage () != null ) {
1055+ // Show the Package Explorer view using its ID
1056+ window .getActivePage ().showView ("org.eclipse.jdt.ui.PackageExplorer" );
1057+ }
1058+ } catch (Exception e ) {
1059+ System .err .println ("Failed to open Package Explorer view: " + e .getMessage ());
1060+ e .printStackTrace ();
1061+ }
1062+ }
1063+ });
1064+ // Give the view time to open
1065+ MagicWidgetFinder .pause (500 );
1066+ }
1067+
9911068 /**
9921069 * Switches the Liberty run configuration main tab to the JRE Tab. A Liberty configuration must be opened prior to calling this
9931070 * method.
0 commit comments