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?

Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
  • Does it work when you build from the command-line? (e.g., `mvn install`?) – Emil Sit Apr 08 '11 at 15:34
  • 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. – uncaught_exceptions Apr 08 '11 at 17:21
  • 1
    Did you check this out.http://maven.apache.org/plugins/maven-war-plugin/faq.html#attached – uncaught_exceptions Apr 08 '11 at 17:24
  • If I use the warpath plugin, I can build from the command line, but IntelliJ still can't see the class files. – Stefan Kendall Apr 08 '11 at 18:05
  • @doc_180: Good hint, just what I was looking for. I took the liberty of converting that into an answer. – sleske Mar 26 '13 at 15:09

5 Answers5

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.

sleske
  • 81,358
  • 34
  • 189
  • 227
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.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • 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. – Stefan Kendall Apr 08 '11 at 17:06
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. ;)

Will Iverson
  • 2,009
  • 12
  • 22
  • 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. – Stefan Kendall Apr 08 '11 at 17:14
  • 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. – Will Iverson Apr 08 '11 at 17:24
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.

Ralph
  • 118,862
  • 56
  • 287
  • 383
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
Arpit
  • 6,212
  • 8
  • 38
  • 69