I have been reading about why it is more convenient to structure the packages by functionality. I understand that it has greater modularity and that it is easier to navigate in the packages.
However, what happens with projects with modules by layers?
For example:
|example-webapp (com.company.webapp.feature1)
|-example-service (com.company.service.feature1)
|-example-data (com.company.data.feature1)
In this case, modularization with maven already separates the project by layers and internally by functionality, however the functionality is distributed in all layers, which I understand reduces the modularity. But in my opinion it is much more reusable, because if at some point you want to implement an API for example, you simply reuse the service and data modules.
So, in multi module maven project how can I strcuture by feature?
|example-webapp (com.company.feature1)
|-example-service (com.company.feature1)
|-example-data (com.company.feature1)
It is advisable not to consider the layers?
Related
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.
Given our maven projet provides some api for clients to interact with it, those are just few java interfaces which are implemented in interal codebase...
Now if we just build the jar and publish it anyone can see the internal classes we used for implementation, yet we only need few java interfaces to be published (along with few DTO classes maybe)...
Is it possible to pick exactly which java files we want to build jar for and create two artifacts like (product.jar/war and product-api.jar)
Prupose is to limit possible misuse of the code by other teams...
The best is to make separate modules in Maven which represent your modules like:
project-api
which contains only the interfaces and which can be used by others separately.
project-impl
one implementation etc.
The above makes testing easier etc. is a good choice with regards to separation of concerns.
Your question is about securing code instead of maven in general. You can have multi-module maven project but still anyone can download that and decomopile it.
Few thoughts as Java does have inbuilt mechanism to support this but there are workarounds...some thoughts..
When you package a project as jar, don't put.java classes in jar/build.
Well the code can be decompiled back to java but at-least u dont
give .java classes to start with.
You can obfuscate your code with
various available options. Read bit here...
At the extereme,
expose your api as web services where you define a contract for
request/response. No one can see your code...
We are building a small application using different architectural layers such as domain, interface, infrastructure and application. This follows the Onion DDD model. Now I am wondering if there is any benefit in splitting the application into a multimodule maven project. As far as I can see now it seems to make things more difficult than needed. The entire application will be deployed as a single WAR file into a Tomcat container.
Splitting your application makes sense for the following:
When a certain part of the project needs to have new functionality or bug fixes, you can simply focus on that module and run just the tests for it. Compiling a fraction of all the code and running just the related tests speeds up your work.
You can re-use the code from the modules across different projects. Let's assume your project contains some well-written generic-enough code for mail sending. If you later have another project that need mail sending functionality, you can simply re-use your existing module or build upon it (in another module by adding it as a dependency).
Easier maintainability on the long run. Maybe now it seems like a small project. In a few months things might look different and then you'll need to do more refactoring to split things into logical units (modules).
Conceptual clarity (as added by Adriaan Koster).
Concerning the WAR: You can have an assembly module which puts things together and produces a final WAR file from all the related modules.
Initially, this may seem as more work, but in the long-run, modularized projects are easier to work with and to maintain. Most sane developers would prefer this approach.
Using multiple modules forces you to have a hierarchy of dependencies. You have one module which is standalone and doesn't depend on any other of your modules. You have another which only depends on that. It might appear harder than allowing anything to depend on anything else but this approach results in a mess of dependencies which is hard to fix later.
If you are trying to follow a layered model I suggest you place each layer in a different module. This will ensure you are not tempted to break the model.
Short answer: today it is small, tomorrow it will bigger and more complicated to maintain, reuse, extend, integrate with other system and so on
As far as I know, Maven do little help for WAR dependencies. As you are talking about single WAR, this should never be a problem.
You can separate java classes into several "jar" submodules, but if you split the WAR project into several smaller WARs, using some kind of "overlapped" packaging things get complicated.
Just information, one of our projects, it contains too many web pages, so we decided to split it into several WAR submodules, however, the session is not shared between different WARs deployed, and we are not going to use Kerberos stuff. At last, we modified a lot sources of Glassfish, Jetty, MyFaces, etc. To make them resolve web.xml stuff inside JARs. And converted the whole project to Facelets 2.0 (to avoid the dependency of JDK tools.jar and custom resource handler), the only reason is to change the WAR submodules to JAR submodules, and move all webapp/pages into class resources. So the conclusion, Maven does great job for JAR dependencies, but no WAR or single WAR.
EDIT You can put applicationContext.xml in one of the base submodule, and import it by classpath:com/example/applicationContext.xml. Also Spring 3.0 do have annotation supports, you can make spring auto scan them instead of declaring them all in the xml.
Spliting your project into multiple maven projects is useful if you want to reuse your classes in another project or if your projects are deployed in different configurations.
Maybe think of a webservice - if you are hosting the server, you could build a project for your domain classes (models) and your endpoint interfaces that could be used by server and client. The server would be another project that is build to a WAR.
To develop further clients the first project could be used, too.
Use a parent project for dependency management on common projects (like logging) and different profiles and build configurations.
I have a rather large (several MLOC) application at hand that I'd like to split up into more maintainable separate parts. Currently the product is comprised of about 40 Eclipse projects, many of them having inter-dependencies. This alone makes a continuous build system unfeasible, because it would have to rebuild very much with each checkin.
Is there a "best practice" way of how to
identify parts that can immediately be separated
document inter-dependencies visually
untangle the existing code
handle "patches" we need to apply to libraries (currently handled by putting them in the classpath before the actual library)
If there are (free/open) tools to support this, I'd appreciate pointers.
Even though I do not have any experience with Maven it seems like it forces a very modular design. I wonder now whether this is something that can be retrofitted iteratively or if a project that was to use it would have to be layouted with modularity in mind right from the start.
Edit 2009-07-10
We are in the process of splitting out some core modules using Apache Ant/Ivy. Really helpful and well designed tool, not imposing as much on you as maven does.
I wrote down some more general details and personal opinion about why we are doing that on my blog - too long to post here and maybe not interesting to everyone, so follow at your own discretion: www.danielschneller.com
Using OSGi could be a good fit for you. It would allow to create modules out of the application. You can also organize dependencies in a better way. If you define your interfaces between the different modules correctly, then you can use continuous integration as you only have to rebuild the module that you affected on check-in.
The mechanisms provided by OSGi will help you untangle the existing code. Because of the way the classloading works, it also helps you handle the patches in an easier way.
Some concepts of OSGi that seem to be a good match for you, as shown from wikipedia:
The framework is conceptually divided into the following areas:
Bundles - Bundles are normal jar components with extra manifest headers.
Services - The services layer connects bundles in a dynamic way by offering a publish-find-bind model for plain old Java objects(POJO).
Services Registry - The API for management services (ServiceRegistration, ServiceTracker and ServiceReference).
Life-Cycle - The API for life cycle management (install, start, stop, update, and uninstall bundles).
Modules - The layer that defines encapsulation and declaration of dependencies (how a bundle can import and export code).
Security - The layer that handles the security aspects by limiting bundle functionality to pre-defined capabilities.
First: good luck & good coffee. You'll need both.
I once had a similiar problem. Legacy code with awful circular dependencies, even between classes from different packages like org.example.pkg1.A depends on org.example.pk2.B and vice versa.
I started with maven2 and fresh eclipse projects. First I tried to identify the most common functionalities (logging layer, common interfaces, common services) and created maven projects. Each time I was happy with a part, I deployed the library to the central nexus repository so that it was almost immediately available for other projects.
So I slowly worked up through the layers. maven2 handled the dependencies and the m2eclipse plugin provided a helpful dependency view. BTW - it's usually not too difficult to convert an eclipse project into a maven project. m2eclipse can do it for you and you just have to create a few new folders (like src/main/java) and adjust the build path for source folders. Takes just a minute or two. But expect more difficulties, if your project is an eclipse plugin or rcp application and you want maven not only to manage artifacts but also to build and deploy the application.
To opinion, eclipse, maven and nexus (or any other maven repository manager) are a good basis to start. You're lucky, if you have a good documentation of the system architecture and this architecture is really implemented ;)
I had a similar experience in a small code base (40 kloc). There are no °rules":
compiled with and without a "module" in order to see it's usage
I started from "leaf modules", modules without other dependencies
I handled cyclic dependencies (this is a very error-prone task)
with maven there is a great deal with documentation (reports) that can be deployed
in your CI process
with maven you can always see what uses what both in the site both in netbeans (with a
very nice directed graph)
with maven you can import library code in your codebase, apply source patches and
compile with your products (sometimes this is very easy sometimes it is very
difficult)
Check also Dependency Analyzer:
(source: javalobby.org)
Netbeans:
(source: zimmer428.net)
Maven is painful to migrate to for an existing system. However it can cope with 100+ module projects without much difficulty.
The first thing you need to decide is what infra-structure you will move to. Should it be a lot of independently maintained modules (which translates to individual Eclipse projects) or will you consider it a single chunk of code which is versioned and deployed as a whole. The first is well suited for migrating to a Maven like build environment - the latter for having all the source code in at once.
In any case you WILL need a continuous integration system running. Your first task is to make the code base build automatically, so you can let your CI system watch over your source repository and rebuild it whenyou change things. I decided for a non-Maven approach here, and we focus on having an easy Eclipse environment so I created a build enviornment using ant4eclipse and Team ProjectSet files (which we use anyway).
The next step would be getting rid of the circular dependencies - this will make your build simpler, get rid of Eclipse warnings, and eventually allow you to get to the "checkout, compile once, run" stage. This might take a while :-( When you migrate methods and classes, do not MOVE them, but extract or delegate them and leave their old name lying around and mark them deprecated. This will separate your untangeling with your refactoring, and allow code "outside" your project to still work with the code inside your project.
You WILL benefit from a source repository which allows for moving files, and keeping history. CVS is very weak in this regard.
I wouldn't recommend Maven for a legacy source code base. It could give you many headaches just trying to adapt everything to work with it.
I suppose what you need is to do an architectural layout of your project. A tool might help, but the most important part is to organize a logical view of the modules.
It's not free but Structure101 will give you as good as you will get in terms of tool support for hitting all your bullet points. But for the record I'm biased, so you might want to check out SonarJ and Lattix too. ;-)
We have this constant discussion in our project as to the granularity of our maven modules. We have come to agree that there may be differences in the needs of a framework (like spring) and an in-house application that is always deployed monolithically.
We also agree that it's fairly sensible to hide implementation details of adapters to external systems behind a separate API module, so the implementation classes don't bleed into the classpath of the main implementations.
as
But that's as far as we go. It's a web project so we have modules like "web", "core" and "adapter(s)". We have multiple backends, but we don't require plugability.
What criteria do you use for modularizing in maven ? Which modules do you make for web projects ?
In my opinion, the project division should be pretty fine grained, even for "only a webapp".
I would make separate projects for the data access layer interfaces and implementation, business layer interfaces and implementation, and the webapp itself. I would also make atleast one "commons" project for containing code relevant to more than one of the other projects. But this is just the beginning. I would not hesitate to extract a commons-util project for utility classes relevant regardless of the application that is being developed (String, Date, Reflection, etc). I would also make a project for useful utilities when doing testing (commons-test). And that's just the next step ... ;)
If I wrote generally useful code relevant to hibernate, I would put it in a hibernate-utils project. Useful Spring utilities would go in a spring-utils project etc. When doing this, many projects will only contain a single or a few packages, and the packages will commonly contain few classes.
My reasoning for doing this, is that it helps me think about the code I write. Is this REALLY business logic, or is it general String manipulation, Date manipulation, Hibernate specific logic etc? My layers become cleaner, and it becomes harder to get circular dependencies between packages and projects (we don't want those). In addition, it becomes much easier to reuse code in other projects. There will always be other projects...
I have also found that it is easier for new developers to get a hang of the structure, because the projects become smaller and more manageable; it's easier to start coding when you feel you don't have to under stand everything.
As a last advantage to the fine grained approach, build times reduce because you don't have to build everything every time.