I am trying to create a service registry where all the modules are added as compile(project(..)). The service registry module expose an unified function to call any function from any module. This is to reduce the direct coupling between two modules and to provide a proper separation of concern. To call any function from any module one can add dependency of service-registry as project and get the function. But if we do that the project has circular dependency.
Is there a way I can force gradle to ignore circular dependency,
project root
project A
-- compile(project(':SR'))
project B
-- compile(project(':SR'))
project SR
-- compile(project(':A')
-- compile(project(':B')
I will be moving the dependencies to nexus and use versioning, but in initial phase it would be great if somehow I can force gradle not to do so.
Can it be done by doing some condition as
if(calling_project_name!=root) compile(project(':A'),project(':B'))exclude(project(':calling project name')
is it possible to do? Other suggestions are also welcome.
I am using gradle 2.7.
Related
Experts,
I need some expert advice on how to approach the below use case in spring boot.
I need to have a maven multi-module approach to my project.
I need to have a single jar as output of the final build process.
There are to be common modules for controllers, data access and other functionality
Other modules are to be created based on functionality domain for eg a module for Payroll, a module for Admin etc etc.
Each domain functional module will then have their own controllers extending the common controller, exception handler and so on.
Each module will also have its own set of thyme leaf pages.
The reason for following such an approach is we have development in phases and we will be rolling out based on functional modules.
Here are the issues that I can sense using this approach.
Where do I add the spring web dependency? If I add to the parent pom - it gets replicated across the children and there will be port conflict issues as each module loads. the same issue will also be there the moment I add it to two child modules.
How do I build the fat jar which has all the jars from all modules and works as the final deployment?
All the text that I read i can't see anything even close to what I am trying to achieve.
AD1. They will not unless you are trying to setup independent application context in each module. Of course you can do that(it might be complicated but I believe it's achievable), but for me it's an overkill. Personally I think it's better to have one application context and rely on scanning components that are present in classpath.
AD2. The structure in maven might be a little bit complicated and overwhelming at first glance but it makes sense. Here's how I see it:
Create a parent module that will aggregate each module in project and will declare library/plugin dependencies for submodules.
Create 1-N shared submodules that will be used in other modules. With come common logic, utils, etc.
Create 1-N submodules that will be handling your business logic
Create an application submodule that creates application context and loads configuration and components from classpath
Create a submodule that will be responsible for packaging process, either to war, jar, uber-jar or whatever else you desire. Maven jar plugin should do that for you. For executable uber-jar, you have dedicated tool from spring.
Now you can choose three ways(these ways I know) of loading your modules.
1. Include some modules in maven build based on the build configuration via maven profiles and let spring IoC container load all the components he finds in the classpath
2. Include all of the modules in maven build and load them depending on spring active profiles - you can think about it as of feature flag. You annotate your components or configuration class with #Profile("XYZ") telling spring IoC container whether to instantiate component or not. You will need (most flexible solution) to provide a property file which tells spring which profiles are active and thus which modules should be loaded
3. Mix of these two above.
Solution 1 pros:
build is faster (modules that are not included will be skipped during build)
final build file is light (modules that are not included are... not included ;))
nobody can run module that is not present
Solution 1 contras:
project descriptor in maven may explode as you might have many different profiles
Solution 2 pros:
it's fairly easy and fun to maintain modules from code
less mess in project descriptor
Solution 2 contras:
somebody can run module that is not intended to be run as it's present in classpath, but just excluded during runtime via spring active profiles
final build file might be overweight - unused code is still present in code
build might take longer - unused code will be compiled
Summary:
It's not easy to build well structured project from scratch. It's much more easier to create a monolith and then split it into modules. It's because if you already created a project, you've probably already identified all the domains and relations between them.
Over past 8 years of using maven, I honestly and strongly recommend using gradle as it's far more flexible than maven. Maven is really great tool, but when it comes to weird customization it often fails as it's build capabilities rely on plugins. You can't write a piece of code on the fly to perform some custom build behaviour while buidling your project, you must have a dedicated plugin for doing that. If such plugin exists it's fine, if it's not you will probably end up writing your own and handling its shipment, so anyone in your company can easily perform project build.
I hope it helps. Have fun ;)
When working with gradle multimodule project, is it possible to define functions in parent project but use them in submodules build.gradle.kts?
Note i do not need untyped tasks registered and called with strings... I want actual typesafe code to be shared to submodules.
Ideally without creating a plugin or using buildSrc.
Whats the most to the point way to share a class from parents build.gradle.kts to all submodules?
NOTE : this is not the same as sharing closure trough ext... you loose type safety, what i ask for is Type safety on submodule side.
I'm thinking that there is no way. When a Kotlin build script gets compiled, it will end up as a class called Build_gradle in the default package (i.e. empty package) that extends CompiledKotlinBuildScript. Any class that is defined within a script becomes a public nested class in its corresponding Build_gradle. When the subproject build script gets compiled, it has no access to the classpath that contains the parent projects build script. This makes sense, as there would be multiple Build_gradle files in the same (default) package.
I'd go for buildSrc, to solve the problem, but I'm speculating that what you also wanted was some sort of nice separation of concerns in a multimodule project, not having unrelated projects knowing about what others need to communicate. What you could do to minimize the exposure is to only keep the API (interfaces, data classes) in buildSrc and have a script plugin in a parent project provide the implementation.
I'm currently maintaining a fork of the jodconverter project which offers a spring-boot-starter module, allowing a spring-boot based app to use an Open/Libre Office installation (on the same server) to automate document conversions.
Now, the project have grown and a new module was born, named jodconverter-online. This module will send conversion request to a LibreOffice Online server, and I now want to create a spring-boot starter to support this new module.
The current jodconverter-local (on which depends the current jodconverter-spring-boot-starter) does not have the same dependencies as the jodconverter-online module. This is why they are two separated modules in the first place.
So my question is:
Should I create a new jodconverter-online-spring-boot-starter or if it is possible (and how) to just modify the current starter project, making the dependencies optional according to the needs of the user.
For now I put it all in the current starter project (which is available as a 4.2.0-SNAPSHOT in the OSS snapshot repository), but I'm doing it the wrong way since it automatically adds the dependencies for both the jodconverter-local and the jodconverter-online modules.
You may want to make the dependencies to jodconverter-local and jodconverter-online optional, you just need to replace the keyword compile by compileOnly in your Gradle build file.
Obviously, when dependencies become optional, the developer will have to choose one of the options and add it to their project's dependencies (in addition to your starter).
If the only additional dependency is either jodconverter-local or jodconverter-online, that is no big deal. But if more dependencies have to be added for each case, then you might consider creating a new starter to encapsulate those dependencies.
As for the AutoConfigurations, I don't see any problem with what you did, since you use #ConditionalOnClass to trigger the AutoConfiguration only when the corresponding class is present on the classpath.
I have created a service builder project (Gradle type) in Liferay7 called register-user. There is another service builder project called register-organization. I have a situation where one of the service builders depends upon other. However, i am not able to figure out where to put the dependency of one into another. Is there is any way to do that?
With each servicebuilder project you create from the template, you get two projects, e.g. register-user-api and register-user-service. The -service project depends on the -api project and has the dependency noted in its build.gradle. Look it up and use exactly the same notation to make any other project depend on register-user-api.
The situation changes if both projects do not live in the same workspace: In that case you'll need your own repository (e.g. proxy for Maven Central) where you publish your own modules. Then you can just declare a standard dependency for your modules.
I have a couple of java modules set up in IDEA and I am wanting to mavenize them. These java modules use classes from one another.
I was not quite sure how I should take up this and I decide to add modules on a maven project using IDEA. Hence first I created a maven project, let's name it pm1 which has a class let's name it TempClass1. Now this class can be used in other maven project. Hence I added another maven module - pm11 and tried to use TempClass1 with in pm11. It worked and I notices that IDEA had added module dependency of pm1 in pm11. So whole structure looks as -
But now when I do mvn test from pm11 then it fails with error message package package1 does not exist and it looks to me that it is because package1 is in a different maven project. And I am not sure how I could use classes which reside in a different maven project. I hope I am clear in my question.
You can use classes of other maven projects, as long as there's a proper maven dependency defined in pom.xml. Ensure that the dependency is defined and its' scope is either undefined or relevant (You may have problems if the scope is provided for example).