I am looking to set up a multi module maven project (described below) that would scale well. I have some questions about the approach which is largely drawn from the Sonatype example.
I have done a certain amount of reading on maven multi module projects but couldn't find an example going beyond the basic level.
Questions:
Is this (below) a good project structure to start with? Or does it smell of disaster right from the start - i.e. would lead to heavy restructuring when setting up builds? In short, I am looking to avoid setting up something that goes against the grain with Maven.
I am expecting some modules to be quite independent, while most will be interrelated. Is it alright to start with each module as a Git repo and later refactor in together modules that are tightly linked?
Objectives:
Good project structure for a modular Spring, JSF2, Maven based project, that would allow for builds involving a selection of modules and their dependencies.
It should be possible to deploy an individual web module on a lightweight container like Tomcat/Jetty through Maven configuration (like jetty-maven-plugin). This should be able to pull in the necessary dependencies through Maven. That makes it easy during development to focus on the module being worked on (not having to run a full build and deployment) and deploy the full application only in a complete build.
The setup should allow for multiple distributions based on a selection of modules to be included in the build. I take it this can be achieved through the use of build modules that will pull and package the corresponding modules.
Project structure
Core domain classes.
somapp.core (maven project)
|- someapp.core (maven module)
|- someapp.core.tests
Account Management Domain classes
someapp.accountmgmt
|- someapp.accountmgmt
|- someapp.accountmgmt.tests
component1 domain classes
someapp.component1
|- someapp.component1
|- someapp.component1.tests
Service 1 - # account management (User login)
someapp.accountmgmt
|- someapp.accountmgmt.api
|- someapp.accountmgmt.impl
|- someapp.accountmgmt.mocks
|- someapp.accountmgmt.tests
someapp.service2
|- someapp.service2.api
|- someapp.service2.impl
|- someapp.service2.mocks
|- someapp.service2.tests
|- someapp.service2.cli # CLI access for service2
someapp.service3
|- like above
someapp.accountmgmt.web
|- someapp.accountmgmt.web
someapp.service2.web
|- someapp.service2.web
someapp.service3.web
|- someapp.service3.web
someapp.build1 # bundle accountmgmt and service2 into 1 war file
someapp.build2 # bundle accountmgmt and service3 into 1 war file
somapp.build3 # bundle accountmgmt, service2 and service3 into 1 war file
(i.e. someapp.accountmgmt.web.war, someapp.accountmgmt.jar, someapp.service2.web.war, someapp.service2.jar, someapp.service3.web.war, someapp.service3.jar, someapp.core.jar)
I understand project structures are not set in stone. I would like to set up one that is a good starting point. Suggestions / Links to examples are welcome.
Well for the Spring part it's already discussed and an answer accepted at Spring Configuration in a multi-module project. As far as the general layout I've only seen one WAR per project and services only bundled together if they are related (e.g. UserLoginService would not go together with DomainObjectsService).
I would suggest breaking up the structure into several different projects, with the dependencies (business objects, etc) deployed as JAR projects to a local repo and listed as normal Maven dependencies in the (now different) projects that need them. Then in your app-server you can deploy the apps to different paths (e.g. yourdomain.com/app1, yourdomain.com/service2).
My compliments to your ambition though!
EDIT: There is a way to have multiple WARs if you wish, see this SpringSource blog post about Using a shared parent application context in a multi-war Spring application.
A hierarchy starting with Spring IO through to your artifacts can be done as a single build multi-module project.
Spring-IO (dependencies)
- Your parent pom (custom and further dependency management, plugins etc)
- someapp-parent (really just a container for each -independent- sub-module)
someapp-api (deploy as jar into Nexus
someapp-remote (Implements API and makes REST calls to your web app - also an independent jar)
someapp-web ('war' Exposes REST - JSON - representations of your API domain objects)
someapp-dashboar (Admin console working with the API/web app via remote so you can manage everything, also a 'war')
Spring IO is BTW really good as a blessed set of dependencies that work well together and avoid classloader issues. Well worth migrating your project to use it as the latest version looks pretty up-to-date. I'd also recommend using Spring Boot for your web app(s).
As outlined I think its worth having all your app-related modules build as one so versioning is easier and you can test everything in a single build command. I've recently worked on a project where we keep all these modules separate, and it just means 4x the effort to merge changes, build artifacts, deploy artifacts etc.
Related
I just started developing a project in Spring MVC and i want to know how important Maven is.
The following are the key features of Maven :
Simple project setup that follows best practices - get a new project or module started in seconds
Consistent usage across all projects - means no ramp-up time for new developers coming onto a project
Superior dependency management including automatic updating, dependency closures (also known as transitive dependencies)
Able to easily work with multiple projects at the same time
A large and growing repository of libraries and metadata to use out of the box, and arrangements in place with the largest Open Source projects for real-time availability of their latest releases
6.Extensible, with the ability to easily write plugins in Java or scripting languages
Instant access to new features with little or no extra configuration
Ant tasks for dependency management and deployment outside of Maven
Model based builds: Maven is able to build any number of projects into predefined output types such as a JAR, WAR, or distribution based on metadata about the project, without the need to do any scripting in most cases.
Coherent site of project information: Using the same metadata as for the build process, Maven is able to generate a web site or PDF including any documentation you care to add, and adds to that standard reports about the state of development of the project. Examples of this information can be seen at the bottom of the left-hand navigation of this site under the "Project Information" and "Project Reports" submenus.
Release management and distribution publication: Without much additional configuration, Maven will integrate with your source control system (such as Subversion or Git) and manage the release of a project based on a certain tag. It can also publish this to a distribution location for use by other projects. Maven is able to publish individual outputs such as a JAR, an archive including other dependencies and documentation, or as a source distribution.
Dependency management: Maven encourages the use of a central repository of JARs and other dependencies. Maven comes with a mechanism that your project's clients can use to download any JARs required for building your project from a central JAR repository much like Perl's CPAN. This allows users of Maven to reuse JARs across projects and encourages communication between projects to ensure that backward compatibility issues are dealt with.
Getting started with maven only takes about 10 minutes. Reasons why you should learn maven:
It helps you manage your dependencies very easily so you don't need to add jars to your project classpath manually
You can run unit tests
Has over 20 useful plugins which you can use. Plugins make up lifecycles like test, package which make your work more efficient
You can use it to build your project
The most important thing about it at the beginning is that you don't need to worry about setting up your project by adding dependencies, maven does it for you automatically.
Read this spring guide for building with maven
Any other guides in this section for spring boot has the same mechanism
Here is the simple situation breakdown and I'd like to know if I'm doing this optimally or if there is a better convention. I have created a dummy project just for learning purposes.
I have created a multi module Maven project. Simply the parent POM, with two sibling child POMS, one being a service layer, and the other being a web layer.
The end result goal is to have a fully functioning WAR in the Web project's target folder, that I can simply deploy into a Tomcat.
Here is where I am not clear:
- Both the Service project, and the Web project need to use Spring. The Service project needs to use Spring simply for it's dependency injection purpose. I need to take a simple Dog class, and auto-inject it into the DogService object. That's all working fine.
- Then I need to auto-inject a DogService object into a Dog controller. The Dog controller exists within the Web project in the multi module structure. This is also working fine, because I have declared a dependency in the Web project for the Service project, therefore all Service JARs are included in the final built WAR, from the web project.
1) Is there a way to simply declare a Spring dependency for both child projects without having to declare the dependencies in each child POM.xml? I just want to make sure I'm not duplicating resources. I believe the way to do this is just to declare the dependency in the Parent POM.xml.
2) If I do #1 above ^, is this the optimal way of creating the project? In essence, the WEB module is the one that contains all the final jars, and in essence it's almost as if the SERVICE project doesn't even exist in Tomcat. As far as Tomcat 'knows', all there is, is a bunch of JAR files containing classes, some of them having been written in my WEB module, and some of them having been written in the SERVICE module, all of which is irrelevant to the production/Tomcat environment. True or false?
Thanks!
Is there a way to simply declare a Spring dependency for both child projects without having to declare the dependencies in each child POM.xml? I just want to make sure I'm not duplicating resources. I believe the way to do this is just to declare the dependency in the Parent POM.xml.
Maven is quite intelligent about dependency management and will not "duplicate" resources--it caches each dependency once* and manages the classpath so that all of the projects that you work with share the same jars. In general, declare dependencies in the modules where they're needed; don't clutter up modules or especially parents with random pieces just to avoid occasionally re-specifying a dependency. This is like hauling your boat trailer on your daily commute because you occasionally go to the lake.
Keep in mind that dependencies are transitive, so that if service-module depends on spring-web (does it really, or are you spamming dependencies?), if web-module depends on service-module it will pull in the dependency as well without having to repeat yourself.
If I do #1 above ^, is this the optimal way of creating the project?
No, it isn't. Be minimalist about your dependencies: If you need it, include it, but don't add dependencies "defensively". This will just bloat your deployment and slow down builds, along with adding opportunities for problems like version mismatches.
As far as Tomcat 'knows', all there is, is a bunch of JAR files containing classes, some of them having been written in my WEB module, and some of them having been written in the SERVICE module, all of which is irrelevant to the production/Tomcat environment. True or false?
Mostly false. In a war, your top-level project (web-module) has its classes directly in the archive, and dependencies are embedded as jar file inside it. Tomcat does not distinguish between service-module and your Spring and other dependencies, however.
Better still would be using Spring Boot's standalone jar and embedded container features--Boot will take care of packaging up the jars you need into a single runnable file that doesn't need external support.
*Release dependencies only, but snapshots aren't relevant here.
we have web java ee projects using maven
The projects shared common webpages and their code
i want the optimized way to be able to run every single project (Hr , Payroll ,..) and also the aggregated project ERP
the main problem is WAR dependencies
if module projects can run ,all WARs will contain dependencies which will make ERP build time consuming process
we made temp solution using a variable in parent pom to make modules dependencies provided to make ERP build faster
and switch it off to make modules run
As i know, no team like to make war artifact (web project) dependent on other war artifact. if you want to share login functions, it 's better to integrate single-sign-on module. if you only want to share some logic in the webapp, it's advisable to fork it and make it as a standalone maven project.
I have 3 Java projects with the same entities.
I want to share entities between these projects because entities can evolve during the development phase.
We are thinking about building a jar with entities and sharing it using Maven (with a repository).
Maybe you have another solution ?
I also can recommend to use Maven to share code between projects.
Here are some tips to get started:
Use a Maven Repository Manager such as Nexus. It will help you to
create a stable development environment.
Every developer (also the Continuous Integration Server user) should configure their settings file to use your Maven Repository
Manager. Don't specify your repositories in the POMs, confiugre them
only in your Maven Repository Manager.
http://www.sonatype.com/books/nexus-book/reference/maven-sect-single-group.html
Use the dependencyManagement and pluginManagement elements of your parent POMs to specify all versions of the plugins and dependencies
you are using. Omit these versions in the other POMs (they will
inherit them from the parent POM).
I also recommend to use different POMs for multi-module builds and parent POMs.
If you want to share common interfaces, classes, functionality or components, Maven is the way to go. In addition to the dependency management, you also get the added bonus of a standard project layout that will simplify things. Easy integration with most common continuous integration servers and a standard release process are further benefits.
Definitely take a look at Maven!
making an own JAR-library is definitely a good solution.
The jar-file is easy to distribute via dependency management (maven, ivy, gradle ..)
The jar is versioned
The projects using the library can be tested against a certain verion. Otherwise it may gets a problem if you change enties and forget to change a depending project. -> integration tests
Regards
Entities are the representation of a given object am I correct? If so the default mechanism implemented by Java is Object serialization - http://en.wikipedia.org/wiki/Serialization. In the case of jar files if an entity changes you would have to change jar once again each time as well. It may be tedious.
Geneate a standard war file in roo.. But then change it's package to jar file.
Then from any standard war file you can just deploy this jar (Ill use the jar as a maven dependency). Ill maintain a unique named applicationConext like pizzaShop-applicationContext.xml and like pizzaShop-applicationContext-jpa.xml. so from a parent spring project I can stack up various roo projects in this fashion.
Ill also keep their generated webapps folder to allow for the generator to work more easily. (This means I have to open up the pom.xml and keep changing it back to jar). Also helps with cut and paste fodder for non roo generated war files web.xml entry additions.
Seems like it may be a confusing point about roo.. You can just mix and match these jars as you would any spring project. They function like self contained units of springness and work fine sitting side by side with other spring jars all under the same webapp/web.xml context.
Its tedious but still better then writing spring code by hand.
using IDEA ultimate, how would I start a project and have the following layout:
/src/
/src/main/java/com/example/myapp
/src/main/resources
/src/main/webapp
/src/main/webapp/META-INF
/src/main/webapp/WEB-INF
/src/main/webapp/WEB-INF/jsp
/src/main/webapp/WEB-INF/lib
/src/main/webapp/WEB-INF/myapp-servlet.xml
/src/main/webapp/WEB-INF/web.xml
So from what I understand, once this is setup I have to now somehow wire things using Modules/Artifacts/Facets.
I have JDK and tomcat setup.
I just don't know how to wire things up, so when I hit RUN it will build, deploy the app.
The best way to start creating a web project in Idea is to use either a maven project (any project with valid pom.xml and by your folder structure I guess thats what you are trying to do) Or create a project and add a web module (a module with web facet). Artifacts are like your build artifacts, your wars, jars and such things. Modules are sub projects or logical division of your main projects like common module, services, web module in a main project. Facets gives your some extra features like spring auto completion. It tells the IDE that your module is using so and so technology...