Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parent pom and microservices

  • We have several projects that are microservices, every project is independent (running on separate spring boot server, exposing rest services, using separate DB schema...)
  • We use maven to manage the dependencies.

Is it a good idea to have a parent pom declaring each microservices as modules? And so helping to manage the common dependencies (like the lib servlet-api witch is used in every project, to remove it of all of them and declare it in only the parent pom)

like image 938
Emilien Brigand Avatar asked Jan 09 '15 16:01

Emilien Brigand


People also ask

What is parent pom?

A parent pom. xml file (or super POM) in Maven is used to structure the project in order to avoid redundancies and duplicate configurations by using an inheritance between different pom. xml files. If any dependency or properties are configured in both - parent and child - pom.

How do you use parent pom?

Parent POM Relative PathBy default, Maven looks for the parent POM first at project's root, then the local repository, and lastly in the remote repository. If parent POM file is not located in any other place, then you can use code tag. This relative path shall be relative to project root.

Is Maven a Microservice?

Microservices are so well-known in the IT industry right now that they don't require a special introduction. If you've worked with monolithic programs before, you'll understand how difficult it is to deploy them.

How do I share DTO through microservices?

To solve this, we approach a different method. Thanks to this service endpoint, the Customer service can send an order request through its order client. By using the client module, microservices communicate with each other in a more isolated way. Attributes in the DTO are updated within the client module.


3 Answers

The 'problem' with a multi-module parent pom is that, without complicated profiles, it locks the modules in the same release cycle (assuming you're using the Release Plugin, which you should be).

The way I work with Maven is to have a parent pom that declares:

  • common dependencies (logging APIs, JUnit, etc).
  • common plugins.
  • all dependencies in the dependencyManagement section.
  • all plugins in the pluginManagement section.

Each module delcares the parent pom as its parent but the parent knows nothing about the modules.

The benefit of this comes from the last to two bullets above, the 'management' sections. Anything contained in a 'management' section needs to be redeclared in a module that wants to use a particular dependency or plugin.

For example the parent might look like this:

<project>

  <groupId>com.example</groupId>
  <artifactId>parent</artifactId>
  <version>1.0.00-SNAPSHOT</version>

  ...

  <dependencies>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.7</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>            

  </dependencies>

  <dependencyManagement>

    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.6</version>
    </dependency>        

    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>2.1</version>
    </dependency>

  </dependencyManagement>

  <plugins>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>

  <plugins>

  <pluginManagement>

    <plugins>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <appendAssemblyId>false</appendAssemblyId>
          <descriptors>
            <descriptor>src/main/assembly/assembly.xml</descriptor>
          </descriptors>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>

  </pluginManagement>

</project>

And the module might look like this:

<project>

  <parent>
    <groupId>com.example</groupId>
    <artifactId>parent</artifactId>
    <version>1.0.00-SNAPSHOT</version>
  </parent>

  <groupId>com.example</groupId>
  <artifactId>module</artifactId>
  <version>1.0.00-SNAPSHOT</version>

  <dependencies>

    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>          
    </dependency>        

  </dependencies>

  <plugins>

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
    </plugin>

  </plugins>

</project>

The module would:

  • have dependencies on org.slf4j:slf4j-api:1.7.7:compile, junit:junit:4.11:test and commons-lang:commons-lang:2.6:compile.
  • has the plugin org.apache.maven.plugins:maven-assembly-plugin:2.4
like image 163
Nick Holt Avatar answered Oct 07 '22 21:10

Nick Holt


I would avoid dependencies in the parent pom. It's awkward if one of your (independent) microservices would want some other things. It's weird to have the parent know of each microservice.

You can stick with dependencyManagement though to suggest default versions/scopes if you want. A parent pom is, non the less, very convenient to define plugins, repositories and the like.

Instead, I would group a common set of dependencies into a specific artifact(s), that may be only a single pom with dependencies. Then you can depend on, say "com.example/common-db-dependencies/1.2" to include a standard set of database dependencies, like hibernate, apache derby and JPA specs. (or whatever you're using). A service does not use JPA/SQL could avoid that dependency all together.

Don't entangle yourself though. It's easy to overwork dependency structures if you're trying to cover each case. So, only try to standardize things that really get used by a majority of the services.

like image 36
Petter Nordlander Avatar answered Oct 07 '22 21:10

Petter Nordlander


I would definitely use a parent project.

I've been working for years with both the structures...Microservices and not, modular or not, Ant, Maven and Gradle..

We need to understand that using a parent pom does not mean talk about microservices not coupled and independent:

  • they can be still independent and not coupled using parent pom,
  • they can be still built release and updated in isolation even if you are using a parent pom.

I heard saying "a microservice may need to use different versions for a dependency", well you can, just override the dependency in the specific microservice pom.

We need to focus on "What are here the benefit and what are the cons":

  • Control and standardization: I can manage the common dependencies (with the dependencies management) in a single point, it makes easier to roll out dependencies changes across all the modules, yes we may need different third parties version, but same time we need to avoid losing control over all the dependencies, so exceptions may be allowed but they needs to be balanced with the "standardization"
  • Group management: I can still release just a single module, but I can also manage multi modules releases in a easier way, without having to release module by module, but simply the modules that are under development, in this case I still have a single entry point and all the common dependencies can be overviews withing the parent

And much more:

  • common third parties and platform dependencies management
  • common third parties and platform standardization
  • Full control of the dependencies ecosystem withing the whole application (structured in micro services)
  • common plugins management and standardization
  • reduce duplication and redundant logic.
  • Configurations management and standardization
  • Easier maintenance, change in one place instead of potentially 30 places!!
  • easier to test and roll out common change.

What about the cons? I don't see any for the moment, as exceptions can be managed through overriding common behaviour in the specific microservices pom, I can still manage anything in isolation (build in isolation, release in isolation, deploy in isolation..) There is nothing coupled

Not sure yet what we mean with "it locks the modules in the same release cycle" It does not, unless you are using external SNAPSHOT, I can release a microservice in isolation re-using the same parent version.

for example I can have module 1 declaring Parent 1.0 and be released in isolation without having to run the release process from the parent, I can run it directly on the submodule, but I need to not declare any external SNAPSHOT within the submodule project (you would have same issues with or without parent)

like image 5
ivoruJavaBoy Avatar answered Oct 07 '22 21:10

ivoruJavaBoy