Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running main method from test class via maven

I have the following in my pom.xml:

<build>
   ...
   <plugins>
   ...
      <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>exec-maven-plugin</artifactId>
          <version>1.2.1</version>
          <configuration>
              <mainClass>com.myorg.MyClass</mainClass>
          </configuration>
      </plugin>
   </plugins>
</build>

The class com.myorg.MyClass is in my test source directory, and I am able to run it with the following command:

mvn -e exec:java -Dexec.classpathScope="test"

I want to:

  1. avoid having to use -Dexec.classpathScope="test", but I cannot work out how configure that plugin to look in the test classpath.
  2. write more plugins for other classes (which will each have different configurations), but right now I can only run exec:java. Is there a way to label this plugin so that I call it via that label rather than just say "run whatever is in exec:java"?
  3. pull in a -javaagent property. I have this property defined in my pom.xml, which is being used by test cases. Will my "custom" plugin pick up these properties or do I need to do anything to pull them in?

Here is the properties, which is defined directly under <project>.

<properties>
   <spring.version>3.2.6.RELEASE</spring.version>
   <atomikos.version>3.9.2</atomikos.version>
   <loadTimeWeaverArgLine>-javaagent:"${settings.localRepository}/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar"</loadTimeWeaverArgLine>
</properties>

Attempt with profile

Following on @Michal's suggestion (https://stackoverflow.com/a/30839824/257233) this is what I have tried:

<profile>
   <id>run-importer</id>
   <properties>
      <loadTimeWeaverArgLine>-javaagent:"${settings.localRepository}/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar"</loadTimeWeaverArgLine>
   </properties>
   <build>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.2.1</version>
            <configuration>
               <executable>java</executable>
                  <!--
                     None of these three options work.
                     <commandlineArgs>-javaagent:C:/Users/robbram/.m2/repository/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar</commandlineArgs>
                     <commandlineArgs>${loadTimeWeaverArgLine}</commandlineArgs>
                     <commandlineArgs>-javaagent:"${settings.localRepository}/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar"</commandlineArgs>
                     <argLine>${loadTimeWeaverArgLine}</argLine>
                  -->
               <classpathScope>test</classpathScope>
               <mainClass>com.myorg.MyClass</mainClass>
            </configuration>
         </plugin>
      </plugins>
   </build>
</profile>

I run it with:

mvn -e exec:java -Prun-importer 

I am getting the following exception with either of the options:

[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:java (default-cli) on project TOLTAT-Model: An exception occured while executing the Java class. null: InvocationTargetException: Error creating bean with name 'loadTimeWeaver' defined in class org.springframework.context.annotation.LoadTimeWeavingConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.instrument.classloading.LoadTimeWeaver org.springframework.context.annotation.LoadTimeWeavingConfiguration.loadTimeWeaver()] threw exception; nested exception is java.lang.IllegalStateException: ClassLoader [java.net.URLClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:java (default-cli) on project TOLTAT-Model: An exception occured while executing the Java class. null
   at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:216)
   at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
   at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)

I can confirm that the main class com.myorg.MyClass is being executed. I can see other output from it. I can also confirm that loadTimeWeaverArgLine works in other parts of this POM. It is used successfully for Integration tests:

<profile>
   <id>integration-tests</id>
   <build>
      <plugins>
         <!-- Integration tests require additional loadtime Spring argument -->
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.16</version>
            <configuration>
               <forkMode>once</forkMode>
               <argLine> ${loadTimeWeaverArgLine}</argLine>
               <skip>false</skip>
            </configuration>
         </plugin>
      </plugins>
   </build>
</profile>

Attempt 2 with profile and mvn exec:exec

Upodate (Wednesday, 17th of June 2015, 12:11:17 PM): Following on Michal's latest comment I now have this working as I want:

<profile>
   <id>run-importer</id>
   <properties>
      <loadTimeWeaverArg>-javaagent:"${settings.localRepository}/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar"</loadTimeWeaverArg>
      <log4JConfigArg>-Dlog4j.configuration=file:${project.build.directory}/path/to/log4j.properties</log4JConfigArg>
      <mainClassArg>com.myorg.MyClass</mainClassArg>
      <arg1>foo</arg1>
   </properties>
   <build>
      <plugins>
         <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.2.1</version>
            <goals>
               <goal>exec</goal>
            </goals>
            <configuration>
               <executable>java</executable>
               <classpathScope>test</classpathScope>
               <arguments>
                  <argument>${log4JConfigArg}</argument>
                  <argument>${loadTimeWeaverArg}</argument>
                  <argument>-classpath</argument>
                  <classpath />
                  <argument>${mainClassArg}</argument>
                  <argument>${arg1}</argument>
               </arguments>
            </configuration>
         </plugin>
      </plugins>
   </build>
</profile>

And I run it with:

mvn -e exec:exec -Prun-importer

The advantages of this approach:

  • The whole purpose of this profile is to run "special code" that should never be deployed but needs to make use of code in src and test src.
    • I note Michal's suggestion that this deserves to be a module by itself. If this code base wasn't already so well established (large, old, complicated), I would seriously consider this.
  • It leaves room in case this ever needs to be duplicated, so there is no "competition" regarding what gets run with mvn -e exec:exec.
  • I can specify java agent, log4j and lots of other config using variables that already exist in the pom.
  • I can override any of these arguments on the command line with -Darg1="bar"
like image 905
Robert Mark Bram Avatar asked Jun 15 '15 07:06

Robert Mark Bram


1 Answers

I'm not sure what you're actually going to accomplish by this since it's quite stilted use of Maven. However, all this stuff is technically possible:

1/

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.2.1</version>
    <configuration>
        <mainClass>com.myorg.MyClass</mainClass>
        <classpathScope>test</classpathScope>
    </configuration>
</plugin>

2/

You can use profiles for that and put different plugin configurations in different profile. Then you call:

mvn -e exec:java -Pmy-first-profile

It's really weird however, I think. My recommendation here is to reconsider your case and maybe pick another way or tool for that.

3/

Final solution in the question itself after the author's edit.

like image 140
Michał Kalinowski Avatar answered Oct 17 '22 00:10

Michał Kalinowski