I'm trying to design the architecture of a medium-sized web application in Java and I would like to get some advice on how to do it.
The project consists on a base website plus a number of modules. For instance, one module would provide user registration, another module would offer a web service, and so on...
Whenever I need to deliver the application to a new customer, the ideal thing would be to pick up the modules he wants, do some theming (css, images, maybe jsp) and developing the custom modules he may need, if any.
I've taken a look to maven multi module projects, war overlays, but I find it difficult to partition the application, especially in regard to the modules' configuration (for example, merging a global spring configuration from the modules). Can somebody point me to an example of such a system? Thanks in advance!
merging spring configuration is easy. In each module, package up a spring context file in it's /WEB-INF/classes directory. When you overlay, all classes and resources in WEB-INF classes in the dependency will be put into WEB-INF/classes in your app. (ps, this also works if you package as .jar instead, but you won't be able to overlay .jsp files if you do)
Then it's just a matter of importing them. This is best done by using a set pattern to find the files. Here's an example:
<import resource="classpath*:/module/*-context.xml" />
This will import all the classpath resources that match this pattern.
Annotation based example:
#Configuration
#ImportResource(value={"classpath*:/module/*-context.xml"})
public class MyConfiguration { ... }
It's the web.xml configuration that will cause you more trouble than anything if you have the need to do any web.xml customizations in modules. You could use servlet 3.0 for this of course, but it requires the right server to deploy on.
fwiw, after some experience with plain Spring import we developed tiny framework for osgi-less modularity for Spring. The first problem with import is the bean name clashes you can not have same-named singleton in two contexts, and many other hassles.. tbc https://github.com/griddynamics/banshun
--
Mike
Related
I have two Java + Spring Web 4 (not Spring Boot) web project, the dependencies are managed with Maven and are packaged as WAR.
Since both are almost identical, I'd like to create a common WAR with all the common code and put in these two WARs only the differences.
Here a graphic representation:
Most of the differences are in the #Controller classes, for example, I have some endpoints with a custom annotation in one project and without on the other. Another difference is that there are some differences in the code inside the #Controller classes.
I have seen that often, the Maven Overlay is suggested in a situation like this but it doesn't seem a good solution in this case and is not good during the developments because I'd like to debug each project separately.
Do you have any suggestions?
I want to shared common application context in a multi-war Spring application, so i don't need to defined beans again and again. But i don't want to instantiate those beans defined in this common application context in each webapp. I only want to instantiate those beans once and share by all the webapps. Is it possible? Bare me if i'm wrong.
PS: this common application context exists in jar, which i'll import to every webapps.
1, Below article tell us how to share the common application context, but need to instantiate those beans in each webapp.
How to import spring-config.xml of one project into spring-config.xml of another project?
2, Below is another article i just read, i demo it, but still don't get what i want, beans got instantiated twice. Can someone check this section "Why would you want to use this?" in the article, i don't get it, do they have a solution there, can someone help me here, thanks a lot for your time.
http://spring.io/blog/2007/06/11/using-a-shared-parent-application-context-in-a-multi-war-spring-application/
here is the demo source code in second article: https://github.com/jasonluo/ceciic/tree/master/Research/multiple-contexts-sample
Updates
The problem of case2 is because i didn't deploy as a ear file, thanks Deinum for pointing this out, i'm using tomcat, so there is no way to achieve that.
Our solution now is using REST to access the service webapp which running in a separate server.
Don't, there is usually classloader isolation going on to prevent this. Doing this right usually requires a thorough understanding of classloading, Java EE, packaging and your server.
Having that said there is way to do this as outlined in the blog you posted. You have to:
package both WARs into an EAR (this means you have to use and appserver like WildFly AS and can't just use a servlet engine like Tomcat or Jetty)
package both WARs as "skinny" WARs with at least Spring (and all its dependencies) and the shared beans (and all their dependencies) in the lib/ folder of the EAR instead of the WEB-INF/lib folder of the WARs.
Even then it depends on implementation details of the server. AFAIK it is not guaranteed to work under the Java EE specification. For example it likely won't work in GlassFish.
Update
I can't tell if the output of your demo is correct because I couldn't find a build file.
Yes, Tomcat does not support EARs, you could use Apache TomEE which is very similar and supports EARs (I don't know if TomEE does classloading in a way that makes this work). In theory you could also make use of the common classloader in Tomcat but that would be quite a hack.
There is a way to do it, using Spring Dynamic Modules, but it requires OSGi environment, which is quite different from simple Tomcat. Few articles worth reading:
Deploying Spring MVC applications to OSGi
Hello world style example
Blueprint - a further development on DM
Another blueprint documentation reference to Spring
That being said there is not a lot of up to date information about Spring with OSGi, but it's worth a try to achieve just what you said (but of course, with additional performance cost)
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 would like to develop a web application in Java/Spring/Hibernate serving as a business platform that I could connect plugins to (i.e. CRM plugin, ware plugin, sales plugin). Those plugins could be dependent on other plugins in a tree manner. The parent project would be packaged as war having all the basic configuration and looks (Spring configs, CSS, scripts), ready-to-go user and group management, security settings, etc.
Altogether, I would like it to behave and look a bit like Joomla, but be built using different tools for different purposes. And I have a few questions concerning that project:
Do you know of any open source projects offering such a platform ready to go?
If not, is Maven applicable for managing those plugins?
What is the best way to package and deploy those plugins?
And last but not least, is this the right way to go, or is it a dead end? Would it be better to create a separate web app for those business needs?
There are lots of ways to build plugin modules.
Some Ideas:
You could package every plugin module as a jar and in the classpath root of this jar, put a spring config file with the beans configuration, so if when you are using a specific plugin. You can "turn on" the beans of this package on a web application by simply adding this file to the contextConfigLocation parameter in your web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:module1.xml
classpath:module2.xml
classpath:module3.xml
classpath:module4.xml
</param-value>
</context-param>
So you are able to use those beans in your web application. Another way of doing this, would be to use a more annotations driven approach. Or you can mix the methods.
Some time ago, I structured a way to automatically hot-detect (in execution time, without having to restart the application) plugins in a desktop application by detecting all implementations of a specific abstract class (a contract) in the classpath. So, all that I had to do to build a new plugin, was to implement this "contract". I've used some "classloader" goodies to do this.
When talking about "modules" maybe you would like to see something about OSGi
Well... those are some ideas. I hope it helps in any way. ;-)
I think this is a fine way to design a web application, depending on the requirements. I use plugins because I had several clients using the same codebase with different requirements. If you are developing for one installation, I would say don't waste your time.
Now for the how-to. "Plugins" are a very vague concept. I've used plugins
to intercept method calls
to run background processes
to add additional views in my web application
The question is now, how does this work. The method interceptor works using a org.aopalliance.intercept.MethodInterceptor. The background processors use a TimerTask. The additional views in the web application use Spring MVC routing.
My plugins are packaged as JARs and discovered at application startup time as Spring application contexts.
This is all very general, but might give you some ideas to go off of.
Do you know of any open source
projects offering such a platform
ready to go?
Have a look at Spring Roo
If not is maven applicable for
managing those plugins?
Yes, it is. Check out how AppFuse uses it.
What is the best way to package and
deploy those plugins?
Again, check how Spring ROO or AppFuse does it.
Hope that helps.
*
And last but not least, is this the right way to go, or is it a dead
end? Would it be better to create a separate web app for those
business needs?
*
I have negative experiences in area modularisation with JPA. For example #Entity Customer is included in CRM module, but is intensively used from other. First natural idea one module = own persistence unit is very hard to realise, JPA should be across modules, and modularisation idea is gone to dead end, modules are not separated.
I use kind of modularisation "in process & in JAR", kind of structures is build, some menus / entities etc belong to "modules" in lighter sense
I have a Java/Spring/Hibernate application with a payment module. Payment module has some domain classes for payment subscription and transactions etc. Corresponding hibernate mapping files are there. This module uses applicationContext.xml for some of the configuration it needs.
Also, This module has a PaymentService which uses a paymentDAO to do all database related work.
Now, I want to use this module as it is(without any or minimal re-writing) in my other application(Grails application). I want to bring in the payment module as a jar or copy the source files to src/java folder in Grails.
With that background, I have following queries:
Will the existing applicationContext.xml for Spring configuration in the module will work as it is in Grails? Does it merge with rest of Grails's Spring config?
Where do I put the applicationContext.xml? classpath? src/java should work?
Can I bundle the applicationContext.xml in Jar(If I use jar option) and can overwrite in Grails if anything needs to be changed? Multiple bean definition problems in that case?
PaymentService recognized as regular service? Will it be auto-injected in controllers and/or other services?
Will PaymentDAO use the datasource configuration of Grails?
Where do I put the hbm files of this module?
Can I bundle the hbm files in Jar(If I use jar option) and can overwrite in Grails if anything needs to be changed? Which hbms are picked? or, there will be problems with that?
Too many questions! :)
All these concerns are actually before trying. I am going to try this in next few days(busy currently). Any help is appreciated.
Thanks.
There are a couple of things you'll want to consider:
You'll need to package your applicationContext.xml to avoid namespace clashes - that is, you'll probably put it in src/resources/com/company/module/applicationContext.xml
This application context really needs to be compatible with the grails application - it'll need to access the DB connection used by your app - make sure it doesn't define its own - See section 14 of the docs - http://grails.org/doc/latest/guide/14.%20Grails%20and%20Spring.html
Section 15 of the docs - http://grails.org/doc/latest/guide/15.%20Grails%20and%20Hibernate.html describes using hibernate mapping files
15.4 points out some good articles - http://jasonrudolph.com/blog/2006/06/20/hoisting-grails-to-your-legacy-db/ and http://www.infoq.com/articles/grails-ejb-tutorial
Probably not the exact answer you were looking for, but I hope this helps.