
Question:
Imagine you have environment-specific build which results into two bundles: Home and Office. Environment-specific artifact of your build depends on some common artifact, lets call it 'Core'. It is just a common functionality for Home and Office builds. Home artifact depends on Core, and Office artifact depends on Core. In fact, Home and Office can even be the same artifact which is just build under different Maven profiles: in case we call Maven with -pHomeBundle it builds artifact one way, in case with -pOfficeBundle - it builds it for office, both times taking Core as a dependency which is the same as for Home.
So far so good.
Now a question is: what can we do if Core artifact, which is common for Home and Office bundles has dependencies on other artifacts which are DIFFERENT for Home and Office bundles? I.e. Core artifact is not bundle-dependent, but its dependencies are.
How can we provide our Core with this dependencies?
How can we write Core POM for this?
UPDATE Two solutions were suggested for this problem: add two bundle-specific dependencies to Core project as provided (and then add one real in the bundle-specific module Home/Office which takes Core as a dependency), or add two real dependencies to Core module and then filter them in the bundle-specific module Home/Office. But I cannot get with which dependency Core will be build. No matter we provide it or not - it should be build with some dependency because it goes to repository. As far as I understand it will just take the first available class and use it. So I will have a Core artifact built using one of the dependencies.
Answer1:I would prefer to have those bundle specific dependencies added in their respective pom.xml and exclude them under the core dependencies so that I am 100% sure of getting only those dependent libraries added for that project.
We have encountered a similar situation in our application when we had to build the same application for two different runtimes and some framework libraries had the runtime libraries bundled in them. So we ended up excluding them from the core dependency and included them as individual dependencies to the application POM.
Hope this makes sense and also helps. Curious to learn if legends have a better approach.
Answer2:It sounds like things have gotten a little confused here. You should never really build an environment specific version of your app. You should build only one app, and it should work in any suitable environment, be it home or office. The things that are different should be provided by the environment.
Let's get concrete.
For example: you depended on an oracle database at work, and a mysql database at home. You build your software against a standard interface, say JPA. Your home and work containers (let's assume tomcat), should have a properties file containing the database connection string in a jar in its provided
library folder. Then, when your app starts, it can pick up the environment's database. One app, multiple environments.
Another example: you depend on log4j while at home, but in the office auditing is more rigorous than that and you have to use a custom library. Your code is built against a standard logging interface, and your container at home has the log4j libraries in the provided
folder, when your app is deployed at home it'll pick up the log4j implementation, but your provided
folder at work has the custom logging library so that when your app is started there it picks that up instead.
Hopefully, you can see from these examples that the software we build should be given an environment with environment specific implementations of the services it expects. With modern java, osgi, and modern containers, this is always true. We can always build our software this way. We should not need nor never have environment specific builds.
If you have functionality that's different in each environment, then strip it out into a separate module and mark it as provided in the modules that use it. Usually this will result in at least three modules, one for the interface, and two for environment specific implementations. The interface is almost always a runtime dependency, and the implementations are almost always provided.
Answer3:Re <em>"Home and Office can even be the same artifact"</em>
Do you mean building office
and home
(snapshot or release) with the same GAV <em>and</em> jar file name but with different profiles?
Since a picture is worth a thousand words is it that what you want to achieve:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
office-for-core:jar office:jar
\ / office build
\ /
- - - - - - - - - - - (office-) - - - / - - - - - - - - - - - - - - - -
core:jar core build
- - - - - - - - - - - - (home-) - - - \ - - - - - - - - - - - - - - - -
/ \
/ \ home build
home-for-core:jar home:jar
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -