i have made two maven projects : the first is a generic authentification module with spring security with this structure :
ear
|...warModule
| |...ejbModule
|...ejbModule
the second is a CRM have this structure
ear
|...warModule
|...ejbModule
|...ejbModule
now i want to integrate both so i can manage the CRM security with my authentification project (control url access ,permissions ...)is there a way to do that ?
One way is that, you declare first project as dependency in your second project POM file.
For detail you can check: Maven Dependency Mechanism
Sample code to add Dependencies:
<project>
...
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact 1</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact 2</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>`
Second way and I would suggest to use Overlay approach to integrate multiple modules and another benefit to use overlay is can share common resources across multiple applications.
You have just to add a dependency declaration in one pom.xml file which point to the other artifact. For example lets say the downside lines are your CRM pom file:
<project>
<groupId>crm.group.id</groupId>
<artifactId>crm-artifact-id</artifactId>
<version>1.0</version>
<packaging>ear</packaging>
<dependencies>
<dependency>
<groupId>authentication.group.id</groupId>
<artifactId>authentication-artifact-id</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
It is just a sample and should be updated following your projects/modules group/artifact IDs.
Related
I am working on creating a common library for my team which can be used by different micro-services of our team. Common library will be service-starter which includes : specific spring boot, spring version and other compatible versions and dependencies. Is it possible to guardrail using maven such that our whole team must be on specific MUST versions of some maven dependencies like spring boot version should be common across team (We will also have other maven dependencies which can be overridden in respective micro-service pom if needed.)
You cannot stop your team from defining their own version in their project. However, you can add a <dependencyManagement>tag in your project which will define the versions you wish them to use so they won't have to decide.
But, again, nothing to stop them to override these.
You can create a parent pom that you want and put in <dependencyManagement> the dependencies that you want to be used by applications that use this parent pom.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
so if another application uses as parent pom the one you have declared above and uses as dependency
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency>
</dependencies>
(It does not contain any specific version), it would retrieve by default the version which was delcared in parent pom of 1.0
But the child pom application would always be free to declare their own version if they want, and use that instead, effectively overriding what was declared in parent pom
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
More about Dependency management in Maven
Im looking to create a Spring library project to share across an internal team.
At a very basic concept level The library will send message events to a queue and my plan is to standardise this within a team across several Spring Boot Microservices send messages the same way.
My pom in the library project looks something like this
<artifactId>my-library</artifactId>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
etc...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
I have a service in the library project that looks like this
public class EventService {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public void sendAuditEvent(AuditMessage auditMessage){
Set<ConstraintViolation<AuditMessage>> violations = validator.validate(auditMessage);
if(!isEmpty(violations)){
log.error("Unable to send audit message");
violations.stream().forEach( v-> log.error(v.getMessage()));
}
log.info("Found {} violations", violations.size());
// etc blah blah
return;
}
}
When I import the library into another project my thinking is that I can Autowire the EventService. By adding it in the pom and then
#ComponentScan({"my.library.package.eventlibrary.service"})
How do I prevent spring version locking? If the library is using spring 2.1.5.RELEASE today and the project that imports the library uses a different version would I not end up with potentially maven conflicts?
Also lets say the project that imports the library uses a lower version of hibernate api and the library has 6.0.16.Final. How would I prevent the project from using the newer one found one in the library classpath?
To clarify my question further is there a way I can separate the dependencies in the library from the project that uses it.
Pre Java 9. You can exclude the spring dependencies using maven when you declare the dependency to your module, same goes on for Hibernate. But you can't tell to your module to use a different hibernate version in a WAR.
If you want to work around this you can develop your library as independent micro service expose interface in the form of REST or Websocket if you want full duplex communication or something else JMS whatever....
Post Java 9 you can use java modularity to define the exact dependencies for your jar module. Check Project Jigsaw https://www.baeldung.com/project-jigsaw-java-modularity.
In your case in order to have different versions of the same library (hibernate). You would need two separate class loaders. To achieve this you would need to use layering read here http://openjdk.java.net/projects/jigsaw/spec/sotms/#layers
And here is the source code of many examples including ones that use layers. Focus on them : https://github.com/accso/java9-jigsaw-examples/tree/master/jigsaw-examples
You can try to exclude all transitive dependencies that your library can bring to projects that will use it.
To do this you should replace spring-boot-starter-parent with spring-boot-dependencies in dependencyManagement section and use provided scope for all dependencies which the library needs to work with and which will be exactly used by the projects, that will work with the library.
For example, a pom.xml of your library can be looks like this:
<!-- ... -->
<groupId>com.example</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<spring-boot.version>2.1.5.RELEASE</spring-boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- ... -->
Then you will be able to use your library in the different projects, that use for example the old Spring Boot:
<!-- ... -->
<groupId>com.example</groupId>
<artifactId>old-project</artifactId>
<version>0.13.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.19.RELEASE</version>
<relativePath/>
</parent>
<!-- ... -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>library</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<!-- ... -->
So this project will use hibernate-validator:5.3.6.Final from its spring-boot-starter-web.
Important notes - the code of your library should be 'compatible' with this version of Spring Boot. In other words, you should test your library with different versions of Spring Boot in which you are interested.
See my project as an example.
Might be not what you are looking for, but you can distribute your library as a spring-boot-starter auto configuration module (of course, if the clients are spring boot applications).
This way you can control your dependencies in an agile way and you give your clients more freedom in using the library.
In your particular case, if you need to send a message to a queue you for sure need to have a corresponding classes in classpath. With auto configuration you can have Class Conditions or Been Conditions based on which you can track if your clients have correct configurations in runtime. You can also fail the context loading if something is wrong (providing a meaningful error message).
Spring also provides tracking mechanisms of what could happen if a particular class/library is missing.
I created a maven parent project with three modules :
data-layer-module
data-service-module (uses the data-layer-module)
web-module (uses the data-services-module)
Here is a snippet from the parent pom.xml :
<groupId>org.mygroup</groupId>
<artifactId>myArtifact</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>data-layer-module</module>
<module>data-service-module</module>
<module>web-module</module>
</modules>
The data-layer-module pom.xml contains no dependencies to the other modules (it contains only its external dependencies).
The data-service-module has a dependency in its pom.xml to the data-layer-module :
<dependencies>
<dependency>
<groupId>org.mygroup</groupId>
<artifactId>data-layer-module</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
And the web-module has a dependency to the data-service-module :
<dependency>
<groupId>org.mygroup</groupId>
<artifactId>data-service-module</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
Everything is fine but I don't want the web-module to have access to the data-layer-module. I need to enforce the three layer web-service-data model. Which is not the case with this configuration.
I obviously tried manually excluding it from the web-module pom.xml :
<dependency>
<groupId>org.mygroup</groupId>
<artifactId>data-service-layer</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.mygroup</groupId>
<artifactId>data-layer-module</artifactId>
</exclusion>
</exclusions>
</dependency>
But this causes compilation error since the data-service-module can't find its data-layer-module dependency.
How could this configuration be done ?
If the web module is going to run in the same jvm as the data-service-layer, then a transient dependency to the data-layer-module is necessary - this is why the exclusion you added casuses the application to fail.
You could consider making a simple api, for example data-service-layer-api, which obviously does not depend on data-layer-module, and is implemented correctly by data-service-layer.
You can still use a multi-module maven project, but now you will have 2 artifacts - a web module, and a data-service, which must be deployed separated.
It's basically a tradeoff between strict dependency analysis and project complexity.
I've got a multi-module maven project, with a structure like:
projectA-parent
- module-1
- module-2
And I have another project where I want to bring in all the modules in projectA-parent as runtime dependencies (it's a Spring application, and each module in projectA-parent contains Spring services that I want to be able to autowire).
What I'd like to do is something like
<dependency>
<groupId>projectA-group</groupId>
<artifactId>projectA-parent</artifactId>
<scope>runtime</scope>
</dependency>
so that if I add another module to projectA-parent it is automatically brought in as a runtime dependency (i.e., I don't want to have to add each new module as a dependency in my Spring application as I add them). Is such a thing possible?
You will have to use
<dependencies>
<dependency>
<groupId>projectA-parent-groupId</groupId>
<artifactId>projectA-parent-artifactId</artifactId>
<type>pom</type>
</dependency>
</dependencies>
This will transitively add all dependencies declared in com.my:commons-deps to your current POM.
Using
<dependencyManagement>
<dependencies>
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
works as a simple 'include' of artifacts versions in your dependency management. Thus, it won't add any dependency in your project.
UPDATE:
Another aprroach would be to use a BOM (Bill of Materials). Check this link for the usage of BOM. It is hidden somewhere at the bottom.
You can create a BOM that lists all your modules as dependencies and then you can include the BOM into your pom.xml like this:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>your_bom_group_id</groupId>
<artifactId>your_bom_artifact_id</artifactId>
<version>you_bom_version</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
I guess I'd just add another module that referred to the other modules in your project, e.g.:
projectA-parent
- module-1
- module-2
- module-deps
with module-deps as a jar or pom that depends on module-1 and module-2.
You'll have to update module-deps as you add more modules, but at least it's only in one place.
My goal is pretty simple actually but since there are multiple (and seemingly complex ways to do this) I wonder what I need to do... So I have certain runtime libraries (ADF libraries in particular) that are needed to be added to every project. This parent pom file will just have JAR dependencies in it. How can I use this pom file from a child pom file?
I don't think that using inheritance is a good solution here. Even if every project uses ADF artifacts, you don't want all poms to get these dependencies so declaring them in a corporate parent pom is not really an option.
So, instead, my recommendation would be to create a project with pom packaging to group the ADF dependencies together:
<project>
<groupId>com.mycompany</groupId>
<artifactId>adf-deps</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>some.groupId</groupId>
<artifactId>adf-artifact-1</artifactId>
<version>${jdev.version}</version>
</dependency>
...
<dependency>
<groupId>some.groupId</groupId>
<artifactId>adf-artifact-n</artifactId>
<version>${jdev.version}</version>
</dependency>
</dependencies>
<properties>
<jdev.version>10.1.3</jdev.version>
</properties>
</project>
Then, install/deploy this project and declare it as dependency in any project that needs the ADF artifacts:
<project>
...
<dependencies>
...
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>adf-deps</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
If the child POM file is actually a child (i.e. declares its parent), then it will inherit the dependencies and there is nothing left for you to do.