spring-attic / spring-ide

Spring Development Environment for Eclipse
299 stars 125 forks source link

Run As Spring Boot App does not ignore test classpath #264

Closed bernolanger closed 5 years ago

bernolanger commented 6 years ago

I have a Spring Boot Application that is built by Gradle / Buildship.

When the application is started by "Run As > Java Application" the classpath is computed without the test classes / resources / dependencies.

But when the application is started by "Run As > Spring Boot App" the classpath contains all classes / resources / dependencies. E.g. this results in launching the embedded test database instead of using the configured one. Because of this I can't use the useful Boot Dashboard.

Is this the expected behavior or is there something I can change to get it to work as I expect?

Resolved Buildship Issue

kdvolder commented 6 years ago

If it works correctly for "Run As Java" with BuildShip then it is probably possible for Run As Boot App in STS to be fixed so it would work the same way. This may depend a bit though on how easy it is for STS to tap into BuildShip's correct classpath computation.

But we should definitely have a look at this.

davec76 commented 5 years ago

Hello, is there any idea when this will be looked at? I was hoping it would have been fixed in Buildship 3 but the problem remains and is a problem for many developers at my company. The only workaround we have found is to remove the test classes and resources from the project during development.

kdvolder commented 5 years ago

I was hoping it would have been fixed in Buildship 3

We were hoping this too :-). Does this now work properly in BuildShip when project is run with 'Run as Java' (as opposed to 'run as Spring Boot')? If so then its probably time we should take another look.

kdvolder commented 5 years ago

I have put this issue back into the inbox of our internal tracker.

Apologies, I think the issue fell through the cracks a bit. Our assumption was that a BuildShip fix would be enough to automatically fix this for us too. But it looks like that is not the case. We should look at fixing this ASAP for the boot specific launcher.

Thanks for speaking up and bringing it to our attention.

davec76 commented 5 years ago

I was hoping it would have been fixed in Buildship 3

We were hoping this too :-). Does this now work properly in BuildShip when project is run with 'Run as Java' (as opposed to 'run as Spring Boot')? If so then its probably time we should take another look.

Thanks for the quick reply. I tried running with ‘Run as Java’ and still have the same problem but investigating some more I can see why in our case.

We have a Gradle script for our main project which has lots of sub projects. A simplified example follows:

apply plugin: 'war'
description = 'Deploy'
dependencies {
  compile project(':project-client')
  compile project(':project-server')
}

This creates 3 Eclipse projects, project-main, project-client and project-server. They all have main and test classes in the standard locations.

Printing out the classpath when running with ‘Run as Java’ results in the following: C:/project-main/bin/main/ C:/project-client/bin/main/ C:/project-client/bin/test/ C:/project-server/bin/main/ C:/project-server/bin/test/

Printing out the classpath when running with ‘Run as Spring boot’ results in the following: C:/project-main/bin/main/ C:/project-main/bin/test/ C:/project-client/bin/main/ C:/project-client/bin/test/ C:/project-server/bin/main/ C:/project-server/bin/test/

So the test classes are removed from the main project but not the sub projects. Would this be another bug or have we made a mistake in the way we have defined the sub projects?

kdvolder commented 5 years ago

So the test classes are removed from the main project but not the sub projects. Would this be another bug or have we made a mistake in the way we have defined the sub projects?

I'm not totally sure (not really too expert on all the different ways project structure can be defined in gradle), but I don't think you made a mistake.

My guess is that we are seeing two problems here.

The first problem is that STS doesn't compute the same classpath as BuildShip. So even if BuildShip did get it right STS would still get it wrong. This is something for STS to address somehow.

Second problem (wrong classpath with 'Run as Java' is that BuildShip doesn't get the right classpath for your example (i.e. doesn't work correctly with project dependencies I guess). I think this is something for BuildShip to fix and should be raised as bug against BuildShip in the Eclipse bugzilla tracker.

davec76 commented 5 years ago

Thanks. I have just raised the following BuildShip bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=543214

kdvolder commented 5 years ago

I've started investigating how to fix STS side of things.

Unfortunately, it looks like the way BuildShip implemented the computation for the runtime classpath is not re-usable (unless I re-implement it from scratch or copy paste large chunks of BuildShip code into STS). I would like to avoid this as it is bound to lead to other problems down the line. So I've raised this bug with BuildShip: https://bugs.eclipse.org/bugs/show_bug.cgi?id=543328

In the mean time I will try to find some kind of workaround for the limitation in BuildShip's architecture. I think I have an idea on a bit of a 'dirty' hack to trick BuildShip into executing its classpath computations for our launch configurations.

davec76 commented 5 years ago

As you can see from my comment in https://bugs.eclipse.org/bugs/show_bug.cgi?id=543214 I created a simple Buildship project with one subproject and that worked as expected using "Run as Java'. It did not filter test resources for 'Run as Spring boot'. I haven't been able to work out why our more complex application is not filtering out the test classes. but hopefully Buildship will be able to help me with that.

If you do manage to work out a workaround I am happy to test it on my test project.

spring-projects-issues commented 5 years ago

(comment in Pivotal Tracker added by Kris De Volder:)

I've found a 'workaround' to 'trick' BuildShip into executing the same classpath computations as for plain java launches by making a temporary copy of boot launch configuration as a java launch config.

See: https://github.com/spring-projects/spring-ide/commit/ff7968fbe7ed47353283eed97c08fe48e5c38e8b#diff-4dbd3e986b0586fe308348daf46cff7aR393

Looks like this is working. I've verified the fix with latest snapshot build from update site: http://dist.springframework.org/snapshot/IDE/nightly/

I tested it using a simple boot app. I created it with intializer wizard, selecting 'BuildShip 3.0' as build system. I changed the main method to this:

    public static void main(String[] args) {
        System.out.println(Test.class.getName());
        SpringApplication.run(DemoApplication.class, args);
    }

When running this app from boot dashboard it crashes with a

Exception in thread "main" java.lang.NoClassDefFoundError: junit/framework/Test

This is how it should be (Junit classes are test dependencies and should not be on the runtime classpath). In prior versions of STS this would instead run without errors (which is actually wrong :-)

kdvolder commented 5 years ago

If you do manage to work out a workaround I am happy to test it on my test project.

You can try it from the nightly update site: http://dist.springframework.org/snapshot/IDE/nightly/

Note that this 'fix' should make it so STS now uses the same runtime classpath as buildship 'Run as Java' would. So, I suspect this will not entirely fix your issue unless the bug you raised against BuildShip is also fixed.

kdvolder commented 5 years ago

Note: The proper classpath computation requires some additional (not user-visible) attributes to be set in the launch configuration. These attributes are normally set when a a launch configuration is created. Classpath computation on existing launch configuration may therefore still be broken. Therefore, make sure to delete and recreate existing launch configurations.

davec76 commented 5 years ago

If you do manage to work out a workaround I am happy to test it on my test project.

You can try it from the nightly update site: http://dist.springframework.org/snapshot/IDE/nightly/

Note that this 'fix' should make it so STS now uses the same runtime classpath as buildship 'Run as Java' would. So, I suspect this will not entirely fix your issue unless the bug you raised against BuildShip is also fixed.

This worked on my simple project so thank you for that.

As you suspected I still have the issue with our larger application, I will let send an update if I manage to find the reason for that.

Thanks again for sorting this out.