Maven WAR dependency - cannot resolve package?
Asked Answered
R

5

19

I have a war dependency:

    <dependency>
        <groupId>my.package</groupId>
        <artifactId>myservices</artifactId>
        <version>0.3</version>
        <type>war</type>
    </dependency>

Now, this exists in my local repository, and the class exists at WEB-INF/classes/my/package/myservices. When I go to use myservices, however, I get package my.package does not exist. Intelli-J knows to change myservices into my.package.myservices, but trying to import seems to not work at all.

Is there something special I need to do with this war dependency?

Resupinate answered 8/4, 2011 at 15:29 Comment(5)
Does it work when you build from the command-line? (e.g., mvn install?)Congressman
realized I may have gone on a tangent. I think @seanpatrickfloyd is right. If you want to use war file as dependency then I will try using maven assembly plugin to see if it helps. Yet again sorry for not researching enough on the answer.Imprudent
Did you check this out.maven.apache.org/plugins/maven-war-plugin/faq.html#attachedImprudent
If I use the warpath plugin, I can build from the command line, but IntelliJ still can't see the class files.Resupinate
@doc_180: Good hint, just what I was looking for. I took the liberty of converting that into an answer.Appointee
S
34

It just doesn't work that way. war files are not supposed to be put on the classpath, but deployed to application servers (or servlet containers) that can deal with their special structure.

Of course you can probably find a custom classloader somewhere that can deal with java war files, but it's just not the way to do it.

Keep your code in a jar, include the jar in your war and in this application. But don't use a war as a dependency, unless you are building an EAR file.

Spotty answered 8/4, 2011 at 16:9 Comment(1)
I'm using the grails maven-install plugin, which builds wars only unfortunately. I really don't need the full war, and I would prefer the jar actually.Resupinate
A
37

As pointed out in the other answers:

  • In Maven, you cannot just load classes from a WAR artifact the way you can from a JAR artifact.
  • Therefore, the recommendation is to split off a separate Maven JAR project with the classes you want to reuse, and depend on this project in both the original WAR and the new project.

However, if for some reason you cannot / do not want to split the WAR project, you can also tell Maven that you need a JAR artifact in addition to the WAR. Put this into the POM of your WAR project:

<build>
    ...
    <plugins>
      ...
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <attachClasses>true</attachClasses>
        </configuration>
      </plugin>
    </plugins>
  </build>

Then, when building the WAR project Maven will create a WAR and a JAR from it.

Source: Maven War plugin FAQ

Adapted from doc_180's comment, so it does not get overlooked.

Appointee answered 26/3, 2013 at 15:6 Comment(2)
If you use <attachClasses>, you'll also need to add <classifier>classes</classifier> in the dependency declaration where you reference the jar.Exclusion
Thanks. This helped me help a colleague and it earned me a couple of beers.Hyperactive
S
34

It just doesn't work that way. war files are not supposed to be put on the classpath, but deployed to application servers (or servlet containers) that can deal with their special structure.

Of course you can probably find a custom classloader somewhere that can deal with java war files, but it's just not the way to do it.

Keep your code in a jar, include the jar in your war and in this application. But don't use a war as a dependency, unless you are building an EAR file.

Spotty answered 8/4, 2011 at 16:9 Comment(1)
I'm using the grails maven-install plugin, which builds wars only unfortunately. I really don't need the full war, and I would prefer the jar actually.Resupinate
S
4

WAR dependencies are handled VERY differently by Maven from JAR dependencies. They are treated as overlays.

http://maven.apache.org/plugins/maven-war-plugin/overlays.html

I think what you are looking for is something a bit different from a WAR overlay. WAR overlays merge the file structures with a "closest wins" model, but that means that things like web.xml are replaced by closest wins, not merged.

If you want merging (which is closer to what most people think of when they start talking about WAR dependencies) you should look at the Cargo uberwar plugin.

http://cargo.codehaus.org/Merging+WAR+files

If your goal is simply to share some classes between two WARs, you should probably just put those classes into a JAR project. Maven in particular is really designed to work on a pom.xml -> a single artifact model (JAR/WAR/etc). Trying to take a single pom.xml and have it emit, say, a JAR for some stuff and a WAR for other stuff is going to be very painful.

Incidentally, if you are working on a team larger than one person, you are going to want an artifact management server pretty fast (e.g. Artifactory, Nexus or Archiva) or you will go crazy dealing with this stuff. ;)

Sisterly answered 8/4, 2011 at 17:13 Comment(2)
I'm using Nexus already. I really just need the class model, but the class model is coming from a grails application. The grails maven plugin only pushes wars, unfortunately, and I'd rather not try and do some wonky create-jar then manually-install-jar step as part of the build process.Resupinate
Ah. Yeah, that's still a new artifact - it's going to be VERY hard to get that to work with WAR dependencies. Might try gant to just crack open the WAR, rip out the stuff you need and repackage what you need as a JAR.Sisterly
A
2

In a WAR, the classes must be located at WEB-INF/classes/... not at classes/....

Anyway I never have tried to reference other classes from a WAR (not JAR), and I do not know if this is possible.

Asmara answered 8/4, 2011 at 15:57 Comment(0)
J
0

Make sure the dependency is installed in your local repository.
The local repo should look like:

.m2/my/package/myservices/0.3/myservices-0.3.war

If this is not the case, then install the war into the local repository before using it in the dependency:

mvn install:install-file -Dfile="[path-to-war]"  -DgroupId=my.package  -DartifactId=myservices -Dversion=0.3 -Dpackaging=war -DcreateChecksum=true -DgeneratePom=true
Jardiniere answered 8/4, 2011 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.