I am developing a maven plugin.
When maven instantiates the mojo class, fields annotated as #Parameter will be "dependency injected" by maven, as childenodes are defined inside the project/build/plugins/plugin/executions/execution tag.
Like this:
#Parameter(defaultValue = "${basedir}/src", alias = "src")
private String sourcePath;
will be filled by
<configuration>
<src>${basedir}/whatever</src>
</configuration>
.
Is there a way to get the configuration via some java calls?
I know that I can use
public Xpp3Dom org.apache.maven.plugin.MojoExecution.getConfiguration()
to retrieve that configuration, the problem is that properties are not resolved in this case, so I get "${basedir}/whatever" for sourcePath, ${} of properties are not resolved. I need them resolved, whatever property they are.
Is there a way to get the resolved values runtime?
Thanks
Annotate your mojo with:
#Mojo(name = "mymojoid", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class MyMojo extends AbstractMojo{}
Then the values will automatically be resolved
Related
I upgraded spring from version 2.1.1 to 2.2.0 .
Since then I'm facing the following error when I start my app :
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'ParentService' available: expected single matching bean but found 2: MasterService,SlaveService .
ParentService is an interface :
public interface ParentService{
..
}
MasterService :
#Service
#MasterProfile
public class MasterService implements ParentService{
.....
}
SlaveService :
#Service
#SlaveProfile
public class SlaveService implements ParentService{
.....
}
MasterProfile annotation :
#Profile("MASTER")
public #interface MasterProfile {
}
Slave Profile :
#Profile("SLAVE")
public #interface SlaveProfile{
}
I'm passing to my app the profile with the following flag :
-Dspring.profiles.include=MASTER
According to Spring 2.2 release notes, they have done some changes and forks are enabled by default in maven. As a result the only way to pass params is with the parameter -Dspring-boot.run.jvmArguments . I used -Dspring-boot.run.jvmArguments=-Dspring.profiles.include=MASTER but it still fails..
Passing a profile as a parameter depends on how you run your app. Be careful, the doc you mentioned is referring to the maven spring-boot plugin.
With maven plugin : mvn spring-boot:run -Dspring-boot.run.jvmArguments=-Dspring.profiles.include=MASTER
Classic java app : java -Dspring.profiles.include=MASTER -jar ./myapp.jar
In both cmd line, you can pass more than one parameter, if separated by a ,. See the documentation: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-profile-specific-properties
Since the upgrade, you now have to define your custom profile annotation like this :
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME) // Only this one is really needed
#Profile("SLAVE")
public #interface SlaveProfile {
}
Explaination:
In java, an annotation has a RetentionPolicy, which is similar to a scope. (See this: https://docs.oracle.com/javase/7/docs/api/java/lang/annotation/RetentionPolicy.html).
Without any RetentionPolicy set, the default behavior is an annotation not visible for the JVM (i.e at runtime).
When you want to run your application, you first compile it, which implies converting your .java files into .class file. Your class is only a bunch of byte code, converting your human readable file into a computer language.
Then, when Spring is loading the ApplicationContext, what it does under the hood, among many other things, is reading your .class files. During this process (see class name: org.springframework.asm.ClassReader) Spring loads the annotations that you declare. With what I've said above, during the Runtime, you end up with "two kinds" of annotations :
InvisibleAnnotation: #Retention(RetentionPolicy.COMPILE)
VisibleAnnotation: #Retention(RetentionPolicy.RUNTIME)
To conclude and understand why it was working before:
Spring-boot 2.1.0uses spring-core-5.1.2, which interprets at runtime the visible and invisible annotations, which explain why your #SlaveProfile and #MasterProfile have the expected behaviour.
Spring-boot 2.2.0uses spring-core-5.2.0, which interprets at runtime ONLY the visible annotations, which explain why your #SlaveProfile and #MasterProfile haven't the expected behaviour.
Let's say that Spring "silently" fixed a bug that was reading Invisible Annotation when they shouldn't, but didn't mention it.
Hope it helps!
Adding #Profile will not stop the bean from being instantiated. This is causing the exception. Add #Primary to any beans that the application should not default to.
Ex, add #Primary to the MasterProfile bean.
What do I want to do?
Given a POM file on the local filesystem.
I want to programmatically obtain the effective POM of that POM file. Specifically I want to do the following:
Resolve the POMs dependencies
Ensure that all parent POMs are processed
Obtain the list of dependencies of the fully resolved POM
And so on...
I don't need to obtain transitive dependencies.
What works?
I'm using Maven Resolver Provider which sort of works. However
I have to use a package private class org.apache.maven.repository.internal.DefaultModelResolver
Here a GitHub link to a sample Maven project that you can run: https://github.com/sahilm/maven-resolver-test
The example program does the following:
Downloads the latest spring boot POM from Maven Central.
Prints out it's direct dependencies (with parent deps included)
You can run the the program with:
mvn exec:java -Dexec.mainClass="com.sahilm.maven_resolver_test.Test"
What I need help with?
I need help with understanding why I have to use a package private class to get stuff to work.
Is there another way to get the information I need?
You can create (in your project) a public class under the package: org.apache.maven.repository.internal that extends the package-accessibility class. Just use a class name that is not possible to be used in the furutre by the vendor.
package org.apache.maven.repository.internal;
public class VisibleDefaultModelResolver extends DefaultModelResolver{
public VisibleDefaultModelResolver(RepositorySystemSession session, RequestTrace trace, String context, ArtifactResolver resolver, VersionRangeResolver versionRangeResolver, RemoteRepositoryManager remoteRepositoryManager, List<RemoteRepository> repositories) {
super(session, trace, context, resolver, versionRangeResolver, remoteRepositoryManager, repositories);
}
}
Then your code becomes:
ModelResolver modelResolver = new VisibleDefaultModelResolver(session, requestTrace, "context", artifactResolver, versionRangeResolver, remoteRepositoryManager, repos);
Maybe you can use ProjectModelResolver. Here's a code snippet,
DefaultRepositorySystem repositorySystem =
new DefaultRepositorySystem();
repositorySystem.initService(locator);
ModelResolver modelResolver =
new ProjectModelResolver(session, requestTrace,
repositorySystem, remoteRepositoryManager, repos,
ProjectBuildingRequest.RepositoryMerging.POM_DOMINANT,
null);
I've included a working code here.
I have an aggregator plugin in Maven with an injected DependencyGraphBuilder. My goal is to resolve the DependencyNode of the current project with all child nodes initialized as well.
#Mojo(name = "mojo", defaultPhase = LifecyclePhase.SITE,
requiresDependencyResolution = ResolutionScope.COMPILE, aggregator = true)
public class MyMojo extends AbstractMojo {
#Component(hint = "default")
private DependencyGraphBuilder dependencyGraphBuilder;
#Parameter(defaultValue = "${reactorProjects}", readonly = true, required = true)
private List<MavenProject> reactorProjects;
}
Currently, if i try to resolve to root node, i am only able to get the dependencies of the current project. I assume that Maven did not resolve that dependencies (only for the current project).
dependencyGraphBuilder.buildDependencyGraph(project, null, reactorProjects);
Summing up:
How can i resolve the child nodes to build to full dependency tree
using DependencyGraphBuilder in a Maven reactor project or is this not possible for aggregator projects?
Additional Info:
I have looked at similar questions, but all of those did not assume an aggregator project.
Since you are trying to implement mvn dependency:tree why not to copy the solution from the Maven Dependency Plugin. Take a look at TreeMojo which also uses DependencyGraphBuilder with DependencyNodeVisitor.
I created a maven project, by convention we should put our packages in /src/main/java.
When I create a new package there, if I name it for instance "mypackage" , the package name will not take into account the namespace that I specified in the pom file, i.e "org.company.mypackage"
I end up having a class that looks like this :
package mypackage; // instead of org.company.mypackage
public class MyClass {
public void myMethod() {
...
}
}
The Maven "namespace" (the groupId) in the pom is not automatically prepended to Java packages. You have to do that manually (unless your IDE has some special functionality to do that for you)
Its a common convention to use the groupId and artifactId as base package of your project, but that is not enforced. If your pom contains
<groupId>org.company</groupId>
<artifactId>myproject</artifactId>
then all Java packages should start with org.company.myproject, e.g. org.company.myproject.mypackage.
I'm new to Grails, and I have a problem importing some classes from an external wsdl .
I used wsdl2java to create a class called MacroArgument
package xxxx.MacroArgument;
public class MacroArgument {
...
#XmlElement(name = "MacroArgument")
protected String macroArg;
#XmlElement(name = "ID", required = true, type = String.class)
#XmlJavaTypeAdapter(Adapter1 .class)
#XmlSchemaType(name = "long")
protected Long myParamOverrideID;
....getters/setters...
}
I created a new domain called TestDomainMacro
package it.xxx
import xxxx.MacroArgument;
class TestDomain {
MacroArgument testMacro
static constraints = {
}
}
In eclipse I don't have any problem, while running the application with the command "grails run-app" I have this error:
| Error Compilation error: startup failed:
C:\..pathtofile..\TestDomain.groovy: 3: unable to resolve class xxxx.MacroArgument
# line 3, column 1.
import xxxx.MacroArgument;
Does anyone have an idea of how to solve my problem?
I solved my problem by inserting my class MacroArgument in an external library and then adding the library to the project. Then I imported the class extending a domain of my Grails application.
In which folder is your compiled MacroArgument in Eclipse?
Is it an addition folder? Maybe grails doesn't know about it?
Try to add this folder to grails configuration.
Look into this post
How does you configure your classpath in Eclipse? Check your output in buildconfig.groovy.
grails.project.class.dir = "target/classes"
grails.project.test.class.dir = "target/test-classes"
Maybe grails doesn't know about target/generated-classes/ ?
Just try to compile it in target/classes