Asked  1 Month ago    Answers:  5   Viewed   5 times

We're using maven 2.1.0. I have multiple modules that are completely separate, but still have many common dependencies. Like log4J, but some modules don't need it. I am wondering if it is a good idea to declare all common dependencies in one parent file in the <dependencyManagement> section or is there a better way to deal with this?

A follow up question about <dependencyManagement>. If I declare Log4J in the <dependencyManagement> section of the parent and a sub project does not use it, will it be included anyway?

 Answers

39

Each module should have its own POM and where it declares its own dependencies. This not only tracks external dependencies, but also internal ones.

When you use Maven to build a project it will sort the whole lot out. So if many modules (perhaps all) depend on log4j, then it will only be included once. There are some problems if your modules depend on different versions of log4j but this approach usually works fine.

It is also useful (if there are more than 1-2 developers working together) to set up an internal repository (like Artifactory) and use that internally. It makes it much easier to deal with libraries that are not in the public repos (just add it to your internal repo!) and you can also use build tools to push builds of your own code there so other can use the modules without checking out the code (useful in larger projects)

Sunday, September 5, 2021
 
derobert
answered 1 Month ago
54

You can exclude a dependency in the following manner:

        <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring</artifactId>
                <version>2.5.6</version>
                <exclusions>
                        <exclusion>
                                <groupId>commons-logging</groupId>
                                <artifactId>commons-logging</artifactId>
                        </exclusion>
                </exclusions>
        </dependency>
Wednesday, June 23, 2021
 
mgraph
answered 4 Months ago
46

A little late to the party, but I'll add my two cents. I recently ran into a very difficult to debug issue. I have a parent pom for managing dependencies across multiple projects. I had it set with all the dependencies common amongst them and included groupId, artifactId, version and the most common scope. My thinking would be that I would not have to include scope in the actual dependency section in each project if it fell in line with that most common scope. The problem occurred when some of those dependencies showed up as transitive dependencies. For example if

  • A depends on B at compile scope
  • B depends on C at compile scope
  • C is set to provided in dependencyManagement of parent

Then A's transitive dependency on C is determined to be provided. I'm not really sure if that makes sense or not, but it certainly is confusing.

Anyway, save yourself the hassle, and leave scope out of your dependencyManagement.

Sunday, August 8, 2021
 
aorfevre
answered 2 Months ago
49

As someone already pointed out, the problem is not with limitations to the DI container but with your design.

I see the reason that you have a separate UserService and a JobService which contain a reference to each other. This is because both UserService and JobService contain some logic that needs the other service as a reference (adding a job requires adding a user, etc.). However, I think that you should NOT reference one service from the other. Rather, you should have another layer of abstraction behind the services which the services will use for the common logic. So, the services will contain the logic which can't(shouldn't) be reused and the helpers will contain the shared logic.

For example:

    public class UserHelper{
      //add all your common methods here
    }
    public class JobService {
      private UserHelper us;

      public JobService (UserHelper us) {
        this.us = us;
      }

      public void addJob(Job job) {
 // calls helper class
      }
    }

    public class UserService {

      public UserService(UserHelper js) {
        this.js = js;
      }

      public void deleteUser(User u) {
        // calls helper class
      }
    }   

In this way, you won't have any issues with circular references and you will have one place which contains the logic which needs to be reused by different services.

Also, I prefer having services which are completely isolated from one another.

Saturday, August 21, 2021
 
BradM
answered 2 Months ago
81

Ok, I found a solution that allows me to run just mvn install or mvn deploy and have the jar file installed to the local or remote repository. Inspired by a post to the maven-users list and using the build-helper plugin, in the parent pom, I have:

<pluginManagement>
    <plugins>
        <!-- Attach the jar file to the artifact -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.5</version>
            <executions>
                <execution>
                    <id>attach-artifacts</id>
                    <phase>package</phase>
                    <goals>
                        <goal>attach-artifact</goal>
                    </goals>
                    <configuration>
                        <artifacts>
                            <artifact>
                                <file>${artifactId}-${version}.jar</file>
                                <type>jar</type>
                            </artifact>
                        </artifacts>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</pluginManagement>

And then in the child poms, I have:

<packaging>pom</packaging>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Some of the pieces of this that initially tripped me up:

  • The attach-artifact execution should be under <pluginManagement> so it doesn't get executed if you mvn install or mvn deploy the parent pom.
  • The children need to specify the build-helper-maven-plugin under the build plugins so that code from the parent <pluginManagement> gets run.
  • The children have to be declared as having <packaging>pom</packaging> because you can't add a jar to an artifact if it has the same name as the artifact.

The only downside I see to this approach is that the artifact gets deployed as type pom instead of type jar. But I haven't seen any real consequences of that.

Wednesday, September 22, 2021
 
William George
answered 4 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :