gwt-plugins / gwt-eclipse-plugin

GWT Eclipse Plugin Documentation
http://gwt-plugins.github.io/documentation/
Eclipse Public License 1.0
114 stars 48 forks source link

Eclipse GWTPlugins - can't get the 'Sync the CodeServer running state with the WTP server' to work #320

Open dfht opened 7 years ago

dfht commented 7 years ago

I have a dynamic web project. It has the GWT project facet and has the Sync flag ticked. I have a Tomcat 7 based server that I stop and start from the 'Servers' view as usual. It is configured for the module corresponding to the dynamic web project. I have a code server launcher that is defined with its project set to the aforementioned web project. The code server specifies the launcherDir as the deploy folder of the server app. ,and the server and code server work fine together - it's just that the stop and start of the server does not stop and start the code server, and that would be a nice thing to have working :). Are there any other steps I have missed to tie the two things together properly? This is all on Eclipse Neon by the way..... (and GWT 2.8.0 and the latest GWTPlugins as of 2 days ago)...

dfht commented 7 years ago

When I start the server I get info logs like this in the error log:

GWT: possiblyLaunchGwtSuperDevModeCodeServer: Launching GWT Super Dev Mode CodeServer. launcherId=06413077-5ba1-4ca7-ba52-00434129ef07 launcherDir=I:\NeonTest4\adyptable\Workspaces\J\AdyptWebGenerated\AdyptWebMain\wtpServerGen\Servers\Adypt_Tomcat_7.0\deploy\wtpwebapps\AdyptWebMain

But the launcher it refers to never opens. Now I wonder if this is because I do not use explicit paths in my launcher arguments, but rather I use variables a lot (I do not like the use of absolute file paths in general).

So in this case, my code server launcher specifies its launcherDir like this:

-launcherDir "${projectloc:AdyptWebMain}/wtpServerGen/Servers/Adypt${adypt_prefs_str:adypt.web.main.server.project}/deploy/wtpwebapps/AdyptWebMain

So I use the 'built-in' Eclipse qualified project_loc variable and my own qualified adypt_prefs_str qualified variable (for this I use the Eclipse org.eclipse.core.variables.dynamicVariables extension point to contribute my own variable resolvers).

I have a feeling that the GWT plug-ins make it look for an exact match for the launcherDir and the -wtp.deploy of the web server... Is this so?

If so, you can fix this by making it resolve the arguments first and then test. This is how you can do this:

String launcherArguments = ....... IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
String resolvedLauncherArguments = manager.performStringSubstitution(launcherArguments, false);

Then, check against the resolvedLauncherArguments, and maybe that will fix it?

dfht commented 7 years ago

Oh well it was just a thought..... It might well not be this. I tried changing the code server to an absolute path: So in the code server launcher arguments I have: -launcherDir "I:\NeonTest4\adyptable\Workspaces\J\AdyptWebGenerated\AdyptWebMain\wtpServerGen\Servers\Adypt_Tomcat_7.0\deploy\wtpwebapps\AdyptWebMain"

In the web launcher VM arguments I have:

-Dcatalina.base="I:\NeonTest4\adyptable\Workspaces\J\AdyptWebGenerated\AdyptWebMain\wtpServerGen\Servers\Adypt_Tomcat_7.0\deploy" -Dcatalina.home="I:\NeonTest4\adyptable\Workspaces\J\Tomcat_7.0" -Dwtp.deploy="I:\NeonTest4\adyptable\Workspaces\J\AdyptWebGenerated\AdyptWebMain\wtpServerGen\Servers\Adypt_Tomcat_7.0\deploy\wtpwebapps"

but still no joy...........

Any ideas?

dfht commented 7 years ago

I checked out the video

[https://www.youtube.com/watch?v=LtH4KzmguL0&ab_channel=BrandonDonnelson]

where it said that you don't even need to set the -launcherDir in the code server, so clearly it can't use that to try and match the two launchers. What does it use? I even removed the -launcherDir argument from my code server launcher, and then ,when I start the web server, it still fails to start the code server. However, when I look at my code server launcher, I can see that it has inserted the correct -launcherDir argument (so it seems that it has somehow located it and made the association,, but then still not started it for whatever reason........)...

dfht commented 7 years ago

In the logs, when it claims it is about to start the launcher, it is definitely identifying the correct one as well, as the launcherId it logs is the same as that of my actual code server launcher.....

So why won't it start? Just a reminder - it starts and works perfectly well when started on its own - it's just that the server start-up isn't starting it!

dfht commented 7 years ago

Because I also write and maintain a suite of plug-ins for our platform, I was running by debugging the Eclipse instance from an Eclipse with all of my plug-ins in the workspace. To debug this issue, I loaded the source code for the GWT Eclipse plug-ins (I cloned the master from https://github.com/gwt-plugins/gwt-eclipse-plugin), and guess what? It just worked..... The sync flag of course just works via a debug event listener on the DebugPlugin that starts and stops the code server launcher as the web server launcher starts and stops.

I think that it was always kicking off the CodeServer launcher (via GwtSuperDevModeCodeServerLaunchUtil and ultimatelyDebugUITools.launch(launchConfig, launchMode);) but that the code server launch was always held up by the pre-launch workspace build, which I'm guessing was hanging for some reason in debug mode. This meant that it appeared that the CodeServer launcher was never getting launched. I've seen this behaviour before when debugging plug-ins. I expect that it will just all work outside of the Eclipse debugging set-up, and will verify that next.

dfht commented 7 years ago

No, it's still playing up outside of Eclipse debugging. I just deployed everything to a standalone Eclipse (built my plug-ins and updated the set-up to my latest via my update site - still with version of GWT plug-ins I originally took from update site a few days ago), and still the code server never starts up.... I wonder if there's a fix in master (this is what I debugged with when it worked) that isn't in the plug-ins version I took? I doubt it as the code all looks very simple (start and stop other launcher via debug event listener) to the extent that I doubt it did anything differently before!

I'll keep trying.....

dfht commented 7 years ago

Going back to debugging, it works again, but only if I step through the code up until the time we're actually in the job that does

DebugPlugin.getDefault().getLaunchManager().addLaunch(pendingLaunch);

If I don't step through the code then it the code server never starts up properly. I think this must be some kind of timing issue. I've had the same kind of problem in my own plug-ins before when relying on DebugUITools.launch, and I seem to remember that my problem was in relation to the waiting for all of the outstanding build jobs to finish and joining on the JobManager like below (which is ultimately what happens within DebugUITools.launch)...


public static void launchInBackground(final ILaunchConfiguration configuration, final String mode) {
        final IJobManager jobManager = Job.getJobManager();
        IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore();
        boolean wait = (jobManager.find(ResourcesPlugin.FAMILY_AUTO_BUILD).length > 0 && ResourcesPlugin.getWorkspace().isAutoBuilding())
                || (jobManager.find(ResourcesPlugin.FAMILY_MANUAL_BUILD).length > 0);
        String waitPref = store.getString(IInternalDebugUIConstants.PREF_WAIT_FOR_BUILD);
jobManager.join(ResourcesPlugin.FAMILY_MANUAL_BUILD, new SubProgressMonitor(monitor, 1));
jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, new SubProgressMonitor(monitor, 1));

In my plug-ins I ended up using

DebugUITools.buildAndLaunch(configuration, ILaunchManager.RUN_MODE, sub.newChild(1)) instead.

Anyway I'll have a play and let you know what I find out...

dfht commented 7 years ago

I thought the problem may be that DebugUITools.launch is being called outside of the UI thread. See the comment on the method:

/**
     * Saves and builds the workspace according to current preference settings,
     * and launches the given launch configuration in the specified mode. It
     * terminates the current launch for the same configuration if it was
     * specified via Preferences or toggled by Shift.
     * <p>
     * This method must be called in the UI thread.
     * </p>
     * 
     * @param configuration the configuration to launch
     * @param mode launch mode - run or debug
     * @since 2.1
     */
    public static void launch(final ILaunchConfiguration configuration, final String mode) {
        launch(configuration, mode, DebugUITools.findToggleLaunchForConfig(configuration, mode));
    }

However, changing it to invoke in the UI thread merely means that the server start-up eventually times out. I think this means that it is most likely waiting on the JobManager join I think, which means that the problem may be caused by the JobManager still having a job in the family FAMILY_MANUAL_BUILD, or FAMILY_AUTO_BUILD queued (and which never terminates etc.).

More evidence of this is the fact that if I change to use

DebugUITools.buildAndLaunch(launchConfig, launchMode, new NullProgressMonitor());

instead of DebugUITools.launch then it just works....

I'll try and inspect the job manager to get an idea of what is going on in there........

dfht commented 7 years ago

It's one of those whose behavior is altered too much by debugging/observing it, so very frustrating to solve :)

dfht commented 7 years ago

I can confirm that the fix to this bug is to actually just call DebugUITools.launch from the UI thread. The reason I did not come to this conclusion earlier is that my environment was not actually running the code I thought it was. I had the workspace gwtplugins enabled and those in the distribution disabled in my Eclipse launcher, yet somehow it was running a confused mixture of the two (which I realized after seeing an odd error in the logs - AAAAAAAAARRRRRRGGGHHHHH).

Here's the working version of the GwtSuperDevModeCodeServerLaunchUtil.launch method that consistently and reliably starts up the code server whenever I start the web server:

public static void launch(IProject project, final String launchMode, String launcherDir, String launcherId) {
    try {
      final ILaunchConfiguration launchConfig = findOrCreateLaunchConfiguration(project, launcherDir, launcherId);
      // TODO check for running or terminated launcher and restart it
      //DebugUITools.launch(launchConfig, launchMode);
      Display.getDefault().asyncExec(new  Runnable(){
        @Override
        public void run()
        {
          DebugUITools.launch(launchConfig, launchMode);

        }

      });
    } catch (CoreException e) {
      CorePluginLog.logError(e, "CoreException: Aborting GWT Super Dev Mode Code Server launcher.");
    } catch (OperationCanceledException e) {
      CorePluginLog.logError(e, "OperationCancelException: Aborting GWT Super Dev Mode Code Server launcher.");
    }
  }

I've made the change in a branch of the plug-ins based on master. How do I go about getting this committed and released? What are the credentials when I commit? Is it just my GitHub credentials or do I need some special permissions? If someone else wants to perform the change then that's fine also, but I would quite like to get involved a bit actually.......

dfht commented 7 years ago

I can see my GitHub credentials aren't enough. Fair enough, not just anyone should be able to commit I guess. How do I get to be able to commit?

branflake2267 commented 7 years ago

Nice job debugging and checking it out. I'll need to be able to replicate it before I'll merge something so I'd like to understand it before it goes in. But if you want to fork, create a branch in that fork, then pull against this master. It looks good so far, but I like to replicate the issue. I'm at SenchaCon then fly out for GwtCon on Thursday. Since I'm on the road, I'll have limited amount of time to verify this.

dfht commented 7 years ago

Thanks Brandon, I'll do that. I understand your wish to check it etc. I would be the same with projects here.

To summarize, it's a one line fix to the launch method on GwtSuperDevModeCodeServerLaunchUtil to do:

Display.getDefault().asyncExec(new  Runnable(){
        @Override
        public void run()
        {
          DebugUITools.launch(launchConfig, launchMode);

        }

      });

Instead of

DebugUITools.launch(launchConfig, launchMode);

Bear in mind that the launch method on DebugUITools has in its comment:

* This method must be called in the UI thread.

and the fact that I can empirically verify that without it for me it doesn't work, and with it the sync works.

Thanks again

branflake2267 commented 7 years ago

I don't understand why the change is made other than the statement, did it it cause a lock up of some sort, or from what it sounds like it's a function change for the better. I'm still on the road so I haven't digested the issue quite yet either.

dfht commented 7 years ago

Without the change, the code server fails to start for me when I start the web server(with the 'Sync' flag ticked). It's a bug fix to the issue I raised here .

branflake2267 commented 7 years ago

I don't think this process should run on the UI thread. The launcher initializes the DevMode application or process. Having said that, I hear this is a lock up, so I'm wondering what Eclipse version and OS version you have? And I'm wondering if there might be a dialog trying to pop up on execution that might cause a UI lock up. I'm guessing, but I highly suspect that initializing this process would be not advisable on the UI thread. The same initialization process has been used for some time without problems, but that said, there are a couple dialogs that might do it.

branflake2267 commented 7 years ago

I see what you said earlier, so either way I have to explore it in more details to understand the issue and maybe you're right about the UI thread.