Using Maven to run a WAR dynamically in Tomcat, how does one add classpath entries so only Tomcat sees them?

自古美人都是妖i 提交于 2019-12-06 11:31:14

I may be missing something but why don't you declare the required dependencies in a profile and use this profile when running Tomcat? I don't get why you would need to put these resources at Tomcat's classpath level.

UPDATE: I'm editing my answer to cover the comment from the OP itself answering my question above.

You're correct, the files really need to be in the webapp classpath, not tomcat's. So how could I make a profile that activate automatically for tomcat:run but without additional cmd line args?

I don't know how to do this without declaring the profile as <activeByDefault> or listing it under the <activeProfiles> (but this is not what I had in mind, I would rather use property activation and call something like mvn tomcat:run -Denv=test, not sure to understand why this is a problem).

And how should I "declare the dependencies" in the profile while ensuring that subsequent invocations never let them into the package WAR via a vanilla mvn package

If the previously mentioned profile is active by default, then you'll need to exclude it if you don't want it, by calling something like mvn package -P !profile-1. A profile can't be magically deactivated for one particular goal (at least, not to my knowledge).

Actually, my understanding is that you really have two different context here: the "testing" context (where you want to include more things in the WAR) and the "normal" context (where you don't want these things to be included). To be honest, I don't know how you could distinguish these two situations without specifying any additional parameter (either to activate a profile or to deactivate it depending on the context). You must have valid reasons but, as I said, I don't really understand why this is a problem. So maybe profiles are not a solution for your situation. But I'd really like to understand why because this seems to be a typical use case for profiles :)

UPDATE2: Having read your comment to the other answer and your update, I realize that my initial understanding was wrong (I though you were talking about dependencies in the maven sense). But, I still think that profiles could help you, for example to customize the <resources> as in this blog post (this is just one way to do, using a property like src/main/resources/${env} in the path is another way to go). But this won't solve all your concerns (like not specifying additional command line params or automagically cleaning the target directory). I don't have any solutions for that.

Add the dependencies element directly to the plugin element.

Here is an example of doing the same with the Jetty plugin from the (still in development) Maven Handbook: http://www.sonatype.com/books/mhandbook-stage/reference/ch06s03.html

Vote for http://jira.codehaus.org/browse/MTOMCAT-77 which addresses this need.

Justin Searls

Here's the solution I have in place at the moment.

Special thanks to Pascal's diligent conversation here, but I ultimately decided to make a change to how I was loading my environment-specific config files throughout the goals and now I believe I'm getting most of what I initially wanted.

I removed the config files from <webResources> from the WAR plugin and the test config from <testResources> and am now manually managing the resource-copying with the the maven-resources-plugin to copy them directly into target/classes at the goal they're needed. This way Tomcat can see the config, but the tests aren't broken by having duplicate or differing config files on the path.

It's definitely a mess, but it works. Listing:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.4.1</version>
    <executions>
        <execution>
            <id>copy-env-resources</id>
            <phase>process-resources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>${basedir}/src/main/resources-env/${env}</directory>                                 
                        <filtering>true</filtering>
                    </resource>
                </resources>
                <outputDirectory>${basedir}/target/classes</outputDirectory>
            </configuration>
        </execution>
        <execution>
            <id>copy-testEnv-resources</id>
            <phase>process-test-resources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>${basedir}/src/main/resources-env/${testEnv}</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
                <outputDirectory>${basedir}/target/classes</outputDirectory>
            </configuration>
        </execution>
        <execution>
            <id>copy-env-resources-again</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <directory>${basedir}/src/main/resources-env/${env}</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
                <outputDirectory>${basedir}/target/classes</outputDirectory>
            </configuration>
        </execution>                            
    </executions>
</plugin>

So a mvn clean install will build and test with ${env} and ${testEnv} appropriately. A mvn -Denv=someLocalConfig tomcat:run (which in my case is identical to my default ${testEnv} will make sure the src/main/resources-env/someLocalConfig gets loaded for Tomcat's dynamic execution, but without requiring that I do a clean before successfully rebuilding.

Like I said, messy that I'm rewriting the same cluster of files to the same target location at each phase, but it accomplishes what I'd meant to.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!