Where in Maven should reusable domain and persistence classes go? - java

I have a Maven project that I want to break out into pieces such that my domain and persistence objects can be reused by other maven projects. What would be considered the best approach?
Move the domain and persistent objects into a separate project and have it be the parent POM of any other projects that need it
Put it in a separate project, but make it a jar to be used as a dependency via POM.xml in other projets
Other?

I wouldn't make it a parent project. Sounds like you need two separate projects; one for domain and one for persist.
If the other modules that need to reference your domain are part of the same releasable unit (they follow the same release cycle) then you can make them modules in a multi-module project. If they have different release cycles then you should treat them as separate projects and define the dependency via the normal Maven dependency mechanism.

If it can be broken down into a separate reusable module do so. I usually have a "-domain" project that deals only with domain objects. In the old days I also put in my Hibernate xml files in there.

Related

Cyclic reference in maven multi module project. What can I do to fix it

I'm doing a task where I should design a simple phonebook application divided into modules.
phonebook-api: jaxb classes generated from xsd file, interfaces for repository, DAO and service.
phonebook-server: it consists of implementations of repository, DAO and service. Also it has class for importing xml into database.
phonebook-web: this module has all of the configuration needed for repositories, services etc. Also it has configuration for database. It has a few xml files which are used to generate DBI classes used in DAO and sql scripts to create a simple table to store contacts in phonebook database (it has only one table). In addition, this module has a simple controller.
phonebook-client: simple MBeans application.
This is situation right now:
phonebook-api module depends on phonebook-web, because it needs these DBI classes for DAO interface
phonebook-server module depends on phonebook-api because it needs interfaces for repository, DAO, service. Also it depends on phonebook-web because of these generated DBI classes.
phonebook-web module depends on both of these modules because they are needed for configuration.
So, there are cyclic reference. Can you please help me with this design problem?
The answer is in your question. The problem is with the design. The key to your solution is assign distinct purposes to each module, separate concerns and avoid mutual dependencies.
Other options you can explore include
What seems like an anti-pattern here is that you have a dependency on a web module. This is unlikely to be ideal. You should avoid having module dependencies on units high up the stack. This is what I would try to change first: extract shared code from phonebook-web into one of the shared modules.
Make smaller modules. Maven doesn't have a problem with that.
If a depends on b for package c, and b depends on a for java package d, then you can extract packages c and d into a separate module on which both a and b have a dependency.
Review whether you really need the separate modules.
Maybe having phonebook-api, phonebook-server, and phonebook-web in separate modules isn't necessary after all. Unless you intend to reuse these modules in different applications, you may be better off using the single phonebook-web with all your current modules' code in it.

Maven: difference module - java package

Recently I started to use Maven for managing my project's structure more efficiently. However, since i'm at the same time learning JAVA, i've come to a dead-end, What is the difference between a module in MAVEN and a JAVA package ?
Since packages are used to group classes/interfaces that share common purpose:
(source: docs.oracle)
Definition A package is a grouping of related types providing access protection and name space management.
And i couldn't find a clear definition of a module, better stated than the vague:
(source: http://docs.jboss.org/tools/latest/en/maven_reference/html/creating_a_maven_application.html)
A Maven module is a sub-project
From what i read, we should create modules in order to separate logic in the project, business, domains, basically anything considered a s a separate entity.
Hence, why can't we do the same with usage of packages? Isn't the purpose the same?
I'm also negelecting all build-configurations here. If it's the only difference, then please provide argumentation when which one should be used.
Maven is a bundling tool, it assembles reusable parts of software together to an application, no matter if it is Java code, image resources or HTML templates. It builds your application so it can be run or deployed in a certain environment (local, testing, production etc.) All of this has nothing to do with Java packages.
You should care about Maven Modules if you (or others) want to reuse code that you have written. For instance, you wrote a web application that converts currencies and now you'd like to use the conversion logic (but not the web frontend) in another application. In that case you'd create one module for the web frontend and one module for the business logic.
A package is a collection of classes. A module is a collection of packages with build configuration.
If it was your own project you can organize them however you want with packages and/or modules. If you want to create a re-usable component (e.g. library) for multiple project you should use a module.
If you only have packages a project would have to include all of the packages (i.e. source files) directly for every library that it needed. Instead with module (remeber it also has build configuration) you can take the compiled output (e.g. .jar, .aar, etc) and include that in your project.

Does it make sense to create many Maven parent poms based on project types?

I am trying to understand what would be the best way to organize Maven projects.
Let's say I have these projects -
ProjectA - webapp, uses Spring MVC
ProjectB - util library1,
uses logging, snakeyml
ProjectC - util library2, uses logging,
snakeyml
ProjectD - DAO library, uses logging, uses Spring annotations
A depends on D, D depends on C. B doesn't depend on anything.
I created a parent-pom project with snakeyml, slf4j and log4j as dependencies. I declared this project as parent in B, C and D poms. The parent pom also defines compiler specific properties.
My understanding is that when you declare something as a parent, Maven's inheritance in poms allows the child projects to inherit all the dependencies. If this is correct, should I have multiple parent poms? Let's say, just like parent-pom, should there be a parent-spring-pom, which all spring projects will inherit from? Is this a good practice to have so many different parents, just to have better organization of dependencies, but no logical project hierarchy? Also, I am not declaring the child projects as modules in parent, because some of them are independent libraries. Am I deviating too much from Maven conventions?
You should not group your projects by the technology used but by their function.
Let's say you now consider creating a parent project parent-spring-pom which will have as child Spring projects. What if tomorrow you decide to switch from Spring to JSF? Or a home-grown framework? Worse, you want to switch one of the projects and not all of them? You will have to change the name of every module and this is a pain. The name given to something should not be about how but about what.
This is also true in the context of Maven and multi-module projects.
Note that in your use-case, I don't see the added value of having multiple parents. I feel it complexifies the project more than anything. But you could for example group projects by web-apps, core utilities, data accesses...
Just as an example, consider you have a data-access layer that accesses multiple endpoints (e.g. a web service and a database). It could make sense to group them in a common parent named project-dao and have modules project-dao-wsclient (that will contain the specific code for accessing the web service) and project-dao-db (that will contain the specific code for accessing the database).

How does Maven manage duplicate artifactIds when they belong to a different group?

I'm building some different web projects with Maven and thinking about how to name their artifacts. For the REST API layer, it's convenient to share some classes, so I want to create exchange-api.jar files which will be shared among different projects.
Let's suppose I've got a web application which has it's own exchange-api module. The groupId would be com.mycompany.app1 so the whole maven id for the artifact should be com.mycompany.app1:exchange-api:1.0. Now let's suppose I want to access other app's API from this application. I have to include the dependency com.mycompany.app2:exchange-api:1.0. artifactIds are the same, but the groupId is different. However, both should end up as exchange-api-1.0.jar in the classpath.
How does Maven take care of this? Should I use a unique artifactId for each of them?
Maven manages this problem allowing you to customize the file name mapping, this can be done both for WAR and EAR applications. However I think that your naming convention is poor. Suppose that your projects are publicly downloadable and people not using Maven download them manually and add them to their projects: do you think that a generic "exchange-api" would be clear enough? I think no. Good names are app1-exchange-api and app2-exchange-api. Or simply app1-api and app2-api. There are several examples of this rule: Spring, Hibernate and so on.

Java domain objects shared between projects

I have two Java projects with same domain objects.First project is the administration of a webapp. And second project is the webapp.
I've chosen this approach in order to allow deployment of administration without downtime for my webapp.
So both projects use same database. I'm using spring-data and marking entities with #Entity.
My question is: is there any way to replicate domain objects in each project?
For example creating another maven module with the domain objects and mark as a dependency. (But in this case #Entity will still work?).
the way is just as you said it - create a maven module (usually called datamodel, infomodel or something along those lines) that contains all of your JPA classes (#Entity classes).
this model can either be a completely separate 3rd project (more work) or, more likely, pick one of the 2 projects as the "owner" of the module and the other project will simply list it as a dependency. in both cases you'll need to think about things like version compatibility (what happens when you update administration but not the webapp and the entities changed? who updates the database, how do you make sure the older code can still read/write it?)
as for working, JPA classes work just fine in their own jar.
Like you have raised is a good approximation, separating two different maven projects.
What you're trying to do is very similar to the structure of Broadleaf Commerce. It is a multi-module project using Maven and Spring, is open source, so you can look at how it is structured to see if it helps.
Here you have another guide of how to implement it step by step. Hope it helps.
It seams that you will need at least three modules.
1st - the domain module with the enitity annotated domain classes;
2nd - the application itself witch depends on the domain module;
3rd - the adm module witch also depends on the domain.
Now that you have a multi-module maven project you should have a 4th project formally listing the other three as its child modules.
P.s.: Resist to the temptation of creating separate git repositories and evolving the versions of the modules separately.(just an advice)

Categories