Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure Maven JRE separately #1137

Conversation

kwin
Copy link
Member

@kwin kwin commented Dec 12, 2022

The value is automatically derived from maven-enforcer rule requireJava

This closes #1134
This closes #1120

@github-actions
Copy link

github-actions bot commented Dec 12, 2022

Test Results

0 tests   - 615   0 ✔️  - 608   0s ⏱️ - 9m 12s
0 suites  -   98   0 💤  -     7 
0 files    -   98   0 ±    0 

Results for commit 1240321. ± Comparison against base commit 8e5cd49.

♻️ This comment has been updated with latest results.

@kwin kwin force-pushed the feature/maintain-jre-version-for-maven-per-project branch from 5e37fdf to 23eee3e Compare December 12, 2022 18:01
@kwin kwin mentioned this pull request Dec 14, 2022
@kwin
Copy link
Member Author

kwin commented Dec 14, 2022

@mickaelistria @laeubi @HannesWell Can you quickly comment, whether that extension makes sense from your PoV. Then I would adjust the test cases accordingly, although this probably requires some more refactoring as the tested Eclipse instance only has one installed JRE....

@laeubi
Copy link
Member

laeubi commented Dec 14, 2022

@kwin can you enhance the PR description a bit more with:

  1. How does it solve the referenced issues
  2. maybe a screenshot that shows previous / new state
  3. add an entry to the release notes

@kwin
Copy link
Member Author

kwin commented Dec 14, 2022

Yes, but only after we have consensus that this is the way forward. Here are some screenshots of the PR:

Project Properties to override the Maven Execution JRE (defaults to either JRE System Library used by the Java Project or if not available falls back to Workspace default configured in Eclipse)
Screenshot 2022-12-14 at 13 53 32

Maven Launch Configuration Properties:
Screenshot 2022-12-14 at 13 54 51

@laeubi
Copy link
Member

laeubi commented Dec 14, 2022

Can you explain what a "Maven JRE" is? The one to run maven commandline build in contrast to the "JRE System Library"?

If yes, maybe this should have two levels:

  1. global JRE configured in m2e config, this should then default to the minimum of the current maven relase (1.7?)
  2. project specific configuration

And we should find a better name, maybe "Maven Runtime JRE" or "Maven Build JRE" ....

but in general I think this would be valid, e.g. Tycho requires Java 17 to run, but can compile code for Java 8 ...

@kwin
Copy link
Member Author

kwin commented Dec 14, 2022

Can you explain what a "Maven JRE" is? The one to run maven commandline build in contrast to the "JRE System Library"?

Yes, exactly. Maybe we should relabel as "Maven Execution JRE"

If yes, maybe this should have two levels:

There is already two levels:
a) on project level (by default equal to the Java Build JRE if not stated otherwise by the maven-enforcer-plugin)
b) on launch config level (allows to override a))

I don't think we need a third level here TBH. Also not sure about the minimum enforced by Maven itself, this is currently not enforced at all, but we could improve later on to also consider this.

@laeubi
Copy link
Member

laeubi commented Dec 14, 2022

Yes, exactly. Maybe we should relabel as "Maven Execution JRE"

Do you think it would be possible to show the one currently active on the left like it is done for Java Projects?

I don't think we need a third level here

Alright then start with this one.

@kwin
Copy link
Member Author

kwin commented Dec 14, 2022

Do you think it would be possible to show the one currently active on the left like it is done for Java Projects?

Where? Please share some screenshot because I don't know what you are referring to.

@laeubi
Copy link
Member

laeubi commented Dec 14, 2022

grafik

@kwin
Copy link
Member Author

kwin commented Dec 14, 2022

I don't think the Maven Execution JRE should be listed in the project explorer as it has zero impact on the (compile or test) classpath!

@laeubi
Copy link
Member

laeubi commented Dec 14, 2022

If it has no impact why do we configure it fro the project? I don't think this is reserved to "classpath" items and as it is a persistent property of the project it seems important enough.

@kwin
Copy link
Member Author

kwin commented Dec 14, 2022

If it has no impact why do we configure it fro the project?

I didn't say that!

I don't think this is reserved to "classpath" items

For me it is, it makes no sense to list anything else being configured on the project properties there.

@kwin
Copy link
Member Author

kwin commented Dec 20, 2022

@mickaelistria @laeubi @HannesWell Can you quickly comment, whether that extension makes sense from your PoV. Then I would adjust the test cases accordingly, although this probably requires some more refactoring as the tested Eclipse instance only has one installed JRE....

I take the silence here as consent, i.e. will work on adjusting test cases, labels and an entry for the release notes

@laeubi
Copy link
Member

laeubi commented Dec 20, 2022

Yes please go on...

@kwin kwin force-pushed the feature/maintain-jre-version-for-maven-per-project branch 5 times, most recently from 3214f9f to 25f6d57 Compare December 21, 2022 17:22
Copy link
Contributor

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general this change looks good and I agree that it is the right direction to let the enforcer plugin only influence the JRE to run a Maven-build process and the adjust the Maven launch config to use that EE by default, but not to consider the enforcer-p when setting the JRE_CONTAINER to build.

But I'm not so happy to handle all of that in m2e.core and therefore introducing a dependency to jdt for m2e.core.
Wouldn't it be possible to handle the selection of the JRE to launch completely in the m2e.launching plugin? Letting m2e.core.ui depend on m2e.launching is probably less problematic.

To test it, wouldn't it be sufficient to check the selected EE and to test the VMInstall algorithm in a unit test.

RELEASE_NOTES.md Outdated

![Maven Project Properties](https://user-images.githubusercontent.com/185025/208966384-816570f8-8c02-4578-bd67-588f7d8e2c27.png)

The default value is automatically set according to the configuration of the `maven-enforcer-plugin` rule [`requireJavaVersion`](https://maven.apache.org/enforcer/enforcer-rules/requireJavaVersion.html) when creating or updating the Maven configuration. This value is no longer considered for configuring the project's build JRE.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should also be noted that the maven-compiler source/target-release settings are considered as well, but may be narrowed-down/pulled up by the enforcer-plugin.

Furthermore I would state first that the projects (build/classpath) JRE_CONTAINER no longer considers the maven-enforcer-plugin but that it is considered as default for the new option of the Maven-Runtime JRE.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically the Maven Execution JRE falls back to project build JRE or workspace JRE when no enforcer rule is found!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rephrased this now, please check.

Comment on lines 77 to 78
final IJavaProject javaProject;
javaProject = JavaCore.create(project);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
final IJavaProject javaProject;
javaProject = JavaCore.create(project);
IJavaProject javaProject = JavaCore.create(project);

@@ -54,10 +72,28 @@ public class MavenProjectPreferencePage extends PropertyPage {

// private Button includeModulesButton;

//https://git.eclipse.org/c/jdt/eclipse.jdt.debug.git/tree/org.eclipse.jdt.debug.ui/plugin.xml#n2467
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should include a specific commitId in the link. Otherwise the the line-number might become wrong one day.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code removed

Comment on lines 43 to 45
private static final Map<String, IVMInstall> INSTALLED_JRES_PER_ENVIRONMENT_ID = Map.of("JavaSE-1.8",
new TestJREManager.JRE("1.8"), "JavaSE-11", new TestJREManager.JRE("11.0.4"), "JavaSE-13",
new TestJREManager.JRE("13.0.3"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static final Map<String, IVMInstall> INSTALLED_JRES_PER_ENVIRONMENT_ID = Map.of("JavaSE-1.8",
new TestJREManager.JRE("1.8"), "JavaSE-11", new TestJREManager.JRE("11.0.4"), "JavaSE-13",
new TestJREManager.JRE("13.0.3"));
private static final Map<String, IVMInstall> INSTALLED_JRES_PER_ENVIRONMENT_ID = Map.of( //
"JavaSE-1.8", new JRE("1.8"), //
"JavaSE-11", new JRE("11.0.4"), //
"JavaSE-13", new JRE("13.0.3"));

Comment on lines 88 to 97
IClasspathEntry entry = null;
for (int i = 0; i < classpath.length; i++) {
entry = classpath[i];
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_VARIABLE:
throw new IllegalStateException("Classpath entries of type CPE_VARIABLE not supported");
case IClasspathEntry.CPE_CONTAINER:
return resolveJRE(entry.getPath());
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
IClasspathEntry entry = null;
for (int i = 0; i < classpath.length; i++) {
entry = classpath[i];
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_VARIABLE:
throw new IllegalStateException("Classpath entries of type CPE_VARIABLE not supported");
case IClasspathEntry.CPE_CONTAINER:
return resolveJRE(entry.getPath());
}
}
for (IClasspathEntry entry : classpath) {
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_VARIABLE:
throw new IllegalStateException("Classpath entries of type CPE_VARIABLE not supported");
case IClasspathEntry.CPE_CONTAINER:
return resolveJRE(entry.getPath());
}
}

defaultJRERadioButton = new Button(comp, SWT.RADIO);
defaultJRERadioButton.setText(getDefaultJreName());
defaultJRERadioButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false, 3, 1));
defaultJRERadioButton.addSelectionListener(new SelectionAdapter() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use SelectionListener.widgetSelectedAdapter() here and below to use a lambda instead of anonymous inner class.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code removed


Button installedJREsButton = new Button(comp, SWT.PUSH);
installedJREsButton.setText(Messages.MavenProjectPreferencePage_btnInstalledJREs);
installedJREsButton.addListener(SWT.Selection, new Listener() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you use addSelectionListener() here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code removed

Comment on lines 247 to 260
// sort by name
Collections.sort(jres, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
IVMInstall left = (IVMInstall) o1;
IVMInstall right = (IVMInstall) o2;
return left.getName().compareToIgnoreCase(right.getName());
}

@Override
public boolean equals(Object obj) {
return obj == this;
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// sort by name
Collections.sort(jres, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
IVMInstall left = (IVMInstall) o1;
IVMInstall right = (IVMInstall) o2;
return left.getName().compareToIgnoreCase(right.getName());
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
});
jres.sort((j1, j2) -> j1.getName().compareToIgnoreCase(j2.getName()));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparator.comparing(IVMInstall::getName, String.CASE_INSENSITIVE_ORDER)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code removed

Comment on lines 34 to 35
public void setUp() throws Exception {
super.setUp();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void setUp() throws Exception {
super.setUp();
public void setUpJREManager() throws Exception {

If you don't override the super-class method you don't have to call super.
Having multiple before-methods is not a problem.

@kwin
Copy link
Member Author

kwin commented Dec 22, 2022

But I'm not so happy to handle all of that in m2e.core and therefore introducing a dependency to jdt for m2e.core. Wouldn't it be possible to handle the selection of the JRE to launch completely in the m2e.launching plugin? Letting m2e.core.ui depend on m2e.launching is probably less problematic.

JDT Launching is necessary when updating projects to calculate the default Maven Execution JRE (and that happens in core)

To test it, wouldn't it be sufficient to check the selected EE and to test the VMInstall algorithm in a unit test.

The Maven Execution JRE is not based on EEs but on concrete JREs.

@laeubi
Copy link
Member

laeubi commented Dec 22, 2022

We already have had the demand to inspect JRE here where it also was quite complex to not do it in core directly:

I therefore thing it would be good to have some kind of JavaToolchainManager interface that abstracts this part and the JDT bundle implements the service.

@kwin
Copy link
Member Author

kwin commented Dec 22, 2022

Then we can not use Interfaces like IVMInstall in that service interface but must define our own one…

@laeubi
Copy link
Member

laeubi commented Dec 22, 2022

Then we can not use Interfaces like IVMInstall in that service interface but must define our own one…

because this is "owned" by JDT and has much more requirements than we need here. So we should decouple m2e.core from jdt.

@laeubi
Copy link
Member

laeubi commented Dec 22, 2022

Beside that I think we can implement most of required stuff in the interface itself, e.g. we can have a method:

setBestMatchingJre(IProject, String);

@HannesWell
Copy link
Contributor

But I'm not so happy to handle all of that in m2e.core and therefore introducing a dependency to jdt for m2e.core. Wouldn't it be possible to handle the selection of the JRE to launch completely in the m2e.launching plugin? Letting m2e.core.ui depend on m2e.launching is probably less problematic.

JDT Launching is necessary when updating projects to calculate the default Maven Execution JRE (and that happens in core)

But why does this have to happen in core? The Maven Execution JRE is eventually just used to select a JRE to run a Maven build?
It is even just the default, based on the compiler- and if present enforcer-plugin configuration, if no JRE/EE was chosen explicitly.
To me that does not sound like that information is required in m2e.core. And therefore I think that is sufficient to have the selection logic in m2e.launching?

To test it, wouldn't it be sufficient to check the selected EE and to test the VMInstall algorithm in a unit test.

The Maven Execution JRE is not based on EEs but on concrete JREs.

Why is it based on JREs/VMInstalls and not EEs anymore? Previously in AbstractJavaProjectConfigurator it was based on EEs. Wouldn't it be better to keep that and use the JRE that is mapped to that version in the workspace?
Or the other ways round, what is the advantage of operating on JRE's directly?

Furthermore I want to challenge the need for a separate preference. All the preference is doing is saving the default Maven Execution JRE of a project, isn't it?
But it is already possible to specify another JRE or EE in a Maven launch config, if the value derived from the compiler- and enforcer-plugin config is not suitable. For me the launch config seems to be the right place to save such choice. And since you can also save a launch-config in a project and put it under version control I see only a little benefit in introducing the preference.
It would only be beneficial in cases where I want to use another JRE than derived from compiler+enforcer (but why is the enforcer-rule not sufficient?) and want to create new launch-configs that I don't want to save in the project?
In general if a project is so special that you need to use a specific JRE then the chances are high that you want to configure other aspects of the build as well and it is therefore reasonable to save the launch config into git.

Therefore my suggestion is to drop the extra preference and just use compiler+enforcer as default. If it later turns out that there is a great demand for such preference we can still add it. :)

@kwin kwin requested a review from HannesWell January 9, 2023 12:44
Copy link
Contributor

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not yet look into the details but from a quick overview my main points I'd like to discuss are the new API and where the enforcer-plugin config is read. Please see the comments below.

*
* @return a version spec compliant with {@link VersionRange} spec
*/
String getRequiredJavaVersion();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a need for that as part of M2E's public API?
Actually I would consider this as internal.

In case there is a real need for that, I would rename it to getExecutionJavaVersion() or similar.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use the IProjectConfig for this! This class is used to group project that have the same resolver context (e.g. selected properties and profiles) but not a general purpose place to store project specific settings, beside that these are workspace specific and cannot be shared.
This should be stored in the preferences (e.g. org.eclipse.m2e.core.prefs or even org.eclipse.m2e.launching.prefs).

/**
* Configure Java version required for Maven execution based on maven-enforcer-plugin configuration
*/
private void configurationRequiredJavaVersion(IMavenProjectFacade facade, IProgressMonitor monitor) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still would prefer to move that to the MavenLaunchDelegate.
This would save the logic to persist that value and unless there is a strong need to make that available in the API (see my other comment), I don't think this is necessary here. Reading the value is not very costly.

@kwin
Copy link
Member Author

kwin commented Jan 9, 2023

To quote from @laeubi s comment from above

So this is no longer relevant?

@HannesWell convinced me that for this purpose it is not required and could be simplified to these steps:

  1. maven-compiler-plugin+maven.enforcer-plugin settings are evaluated an stored as raw values
  2. on launching (if not a custom JRE is selected by the user) these raw values are mapped to the ones configured in JDT

this should reduce the scope of this PR to the minimum and allows it to be merged soon.

You guys really giving me a hard time. I did exactly that in my last update.

*
* @return a version spec compliant with {@link VersionRange} spec
*/
String getRequiredJavaVersion();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use the IProjectConfig for this! This class is used to group project that have the same resolver context (e.g. selected properties and profiles) but not a general purpose place to store project specific settings, beside that these are workspace specific and cannot be shared.
This should be stored in the preferences (e.g. org.eclipse.m2e.core.prefs or even org.eclipse.m2e.launching.prefs).

@laeubi
Copy link
Member

laeubi commented Jan 10, 2023

I think we probably should split this into three parts (and PRs):

  1. Add a way to read/store the RequiredJavaExecutionVersion, but don't change the tests / enforcer parsing / launching / UI ...
  2. change the enforcer parsing to update this RequiredJavaExecutionVersion on project updates
  3. Change the launching part to take this into account, probably UI / test adjustments

That way it would be possible to be more focused and we can probbaly already merge some parts of this than trying to get this done in one big chunck.

@kwin
Copy link
Member Author

kwin commented Jan 10, 2023

I think we probably should split this into three parts (and PRs):

Sorry, not willing to invest that much time here also for me these all belong to the same feature.

Add a way to read/store the RequiredJavaExecutionVersion

As long as you guys have not aligned on this, that won't make any sense. @HannesWell is against persisting it.

@laeubi
Copy link
Member

laeubi commented Jan 10, 2023

Sorry, not willing to invest that much time here also for me these all belong to the same feature.

It seems that the feature is too big to be solved in one change, so a good opportunity is often to split things into smaller pieces, for example all these discussion about the maven-enforcer handling are (for me) unrelated to the topic of supporting a different runtime-jvm and just makes it hard to review the PR and came to a consent.

As long as you guys have not aligned on this, that won't make any sense. @HannesWell is against persisting it.

As said, I think the issue is just to broad and thus things are getting mixed up, the concern was just to compute the enforced java version as part of the (default) project configuration. That is different from the topic of supporting different runtime JVM and that must be persisted somewhere and enforcer might not be the only source (e.g. I really liked the idea of having a user configuration UI for that).

@HannesWell
Copy link
Contributor

You guys really giving me a hard time. I did exactly that in my last update.

Sorry for that, but I can tell you that it is also not fun, if you know that you do that to somebody.

To make your time not even harder, I added the changes how I would do it to another branch:
https://github.com/HannesWell/m2e-core/tree/pr-1137
Basically this moves read of the m-enforcer-plugin from the ProjectConfigurationManager to the MavenLaunchDelegate and reads the config on every launch, without persisting anything.
This also makes the change smaller and less complicated. The current state is definitely not perfect and requires some fixes and streamlining but I hope it makes my suggestion clearer.
If we agree on proceeding like this, I can do the fixes/streamlining and you Konard can then just cherry-pick this and squash this into this PR.

As long as you guys have not aligned on this, that won't make any sense. @HannesWell is against persisting it.

As said, I think the issue is just to broad and thus things are getting mixed up, the concern was just to compute the enforced java version as part of the (default) project configuration. That is different from the topic of supporting different runtime JVM and that must be persisted somewhere and enforcer might not be the only source (e.g. I really liked the idea of having a user configuration UI for that).

Actually with the launch configs we already have a place where to persist a specific runtime JVM if the default is not sufficient. With this change (in the way it should IMHO be done) 'just' the default becomes smarter.
There still could be cases where one needs/wants another JVM than the default and creates new launch configs frequently. Then a project preference could be convenient because the JVM does not have to be adjusted in each launch. But those cases should become much more seldom with this change, so I'm in doubt if there is great demand for an extra preference this.

@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch from 2421cd0 to e92b0d3 Compare February 27, 2023 23:30
@HannesWell HannesWell requested a review from laeubi February 27, 2023 23:30
@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch 2 times, most recently from 3f9fd7e to 257a53e Compare February 27, 2023 23:38
Copy link
Contributor

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kwin and @laeubi
I have now worked out a solution based on what I have described in previous comments, which I believe satisfies all needs. It only considers the enforcer-plugin to select the JRE to run a launched maven build and it does that, without storing anything the projects resolver config, without any new API.

Additionally this approach can read the enforcer config, if if the base-dir/pom-dir points to a project, which is not in the workspace. That is IMHO a quite common scenario, e.g. if one doesn't import the root of a git repo, which often also is the root for a maven build.

Please have a look at it and let me know what you think.
If you are fine with it, it should be submitted ASAP, so that I can release M2E this evening, just in time for 2023-03 RC1.

@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch from 257a53e to 8e65063 Compare February 28, 2023 00:03
@laeubi
Copy link
Member

laeubi commented Feb 28, 2023

Additionally this approach can read the enforcer config, if if the base-dir/pom-dir points to a project, which is not in the workspace. That is IMHO a quite common scenario, e.g. if one doesn't import the root of a git repo, which often also is the root for a maven build.

I must confess I don't understand this part, a configuration should be inherited by its child so it doesn't matter if the parent is in the workspace or not?

IMavenToolbox toolbox = IMavenToolbox.of(ctx);
return toolbox.calculateExecutionPlan(tasks, setup);
}, monitor);
} catch(CoreException e) {
manager.getMarkerManager().addErrorMarkers(pom, IMavenConstants.MARKER_POM_LOADING_ID, e);
exceptionHandler.accept(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part looks suspicious (also in the original) why not just throw the exception and let it handle at the caller site?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is called by IMavenProjectFacade.calculateExecutionPlan/setupExecutionPlan(), which don't permit CoreExceptions in the method signature.
So without breaking the API we cannot propagate the original exception. It would only possible when wrapping it in a RuntimeException.
But I think that would not help much here. It should have been thrown before, but changing it now is not ideal.
But we should note that for a M2E 3.0 :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then wrapping it in a runtime exception (or "handle") it there, this is simply bad style and we should avoid that so pushing the handling as far as possible to the top.

@@ -628,7 +654,7 @@ private MavenProject tryGetMavenProject() {
return manager.getMavenProject(this, null);
} catch(CoreException ex) {
//TODO can we handle this more graceful? E.g. one error condition is that project dependencies can not be resolved, maybe we can try to load the project without dependencies then?
manager.getMarkerManager().addErrorMarkers(pom, IMavenConstants.MARKER_POM_LOADING_ID, ex);
logException(ex);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, better throw the exception to the caller instead and handel it there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Called by IMavenProjectFacade.createExecutionContext().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way would be to return an "ExceptionalExecutionContext" that throws the original exception on any call of its methods (that allow CoreException already), this is also done with the Plexuscontainer as well.

@HannesWell
Copy link
Contributor

Additionally this approach can read the enforcer config, if if the base-dir/pom-dir points to a project, which is not in the workspace. That is IMHO a quite common scenario, e.g. if one doesn't import the root of a git repo, which often also is the root for a maven build.

I must confess I don't understand this part, a configuration should be inherited by its child so it doesn't matter if the parent is in the workspace or not?

That's right. But which project in the workspace should I check if I just have to path the root of a git repo? Iterate over all projects in the WS and check if its within the given path? But then the config could be overridden in a child-project. Maybe different in different childs. Then it's the question which should I take?
Furthermore it can be that one want's to build a project that is not in the workspace at. At least I do that sometimes, for example debugging tests is much simpler when I start the build within Eclipse, than on the CLI.

Considering all those corner cases, it is simpler to just load the pom from the given path and read its enforcer config. It is not the nicest approach, but I think it works in the most robust way.

@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch from 8e65063 to 30c5949 Compare February 28, 2023 09:55
@laeubi
Copy link
Member

laeubi commented Feb 28, 2023

That's right. But which project in the workspace should I check if I just have to path the root of a git repo?

What do you mean by "root of the git repo"? Actually can only execute a pom.xml and then you know what project this resides on and this should be then the MavenProject to query (what might inherit from a pom further down its configuration) ... so what execution we are talking about as m2e always ever only executes one pom, and the childs should not be relevant here, if they define different settings for java I'm not sure if this is something we should consider or is even valid?

@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch from 30c5949 to b48f19f Compare February 28, 2023 22:41
@HannesWell
Copy link
Contributor

That's right. But which project in the workspace should I check if I just have to path the root of a git repo?

What do you mean by "root of the git repo"? Actually can only execute a pom.xml and then you know what project this resides on and this should be then the MavenProject to query (what might inherit from a pom further down its configuration) ... so what execution we are talking about as m2e always ever only executes one pom, and the childs should not be relevant here, if they define different settings for java I'm not sure if this is something we should consider or is even valid?

As we have discussed in private chat, I have now removed the part to load the enforcer-config from a maven-project that is not in the workspace and use only the existing methods on the IMavenProjectFacade.
The reasoning is that we first want to have a general loading of IMavenProjectFacades from a File/Path regardless of if it is in the workspace or not (so something like IMavenProjectFacade.of(File)). Then later we can add use that to load the MavenConfig for a Maven launch.
For now this further simplifies this change, but still fixes mainly intended cases, where one selects Run As > Maven ... on a project in the workspace.

@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch from b48f19f to 452f993 Compare February 28, 2023 23:11
@HannesWell HannesWell linked an issue Feb 28, 2023 that may be closed by this pull request
The value is automatically derived from maven-enforcer rule requireJava

Closes eclipse-m2e#1134
Closes eclipse-m2e#1099
Closes eclipse-m2e#1120

Co-authored-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
@HannesWell HannesWell force-pushed the feature/maintain-jre-version-for-maven-per-project branch from 452f993 to 1240321 Compare February 28, 2023 23:28
@HannesWell
Copy link
Contributor

HannesWell commented Feb 28, 2023

The Jenkins build is green and the GH-workflows fail due to Tycho's current incompatibility with Maven 3.9 (looks like not all runners use Maven 3.9, some use 3.8.7).

So this is ready for submission. Thank you @kwin for starting this PR.

Btw. since this was also an issue discussed in this PR:
Since version 5 Mockito can also mock static methods (and IIRC also final methods) out of the box, which I used here and made testing much easier.

@HannesWell HannesWell merged commit 32dc640 into eclipse-m2e:master Feb 28, 2023
@laeubi
Copy link
Member

laeubi commented Mar 1, 2023

Finally 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants