I am starting a new Java Web Project which is using Hibernate and a standard MVC Architecture.
I have just started to layout the projects structure and while doing this I started to look around to see if there was any standards in this area, about where Controllers should go and generally the best way to lay everything out. However I have not really found any guidelines.
So what I am curious to know is
Is anyone aware of any best practise guidelines for the layout of a Java Web Project?
Does anyone have a particular set of hard rules that they always follow for different types of project?
Do people tend to split packages by the different layers such as presentation, business, and application?
It really depends on your web framework.
For example if you use Wicket, java files and webpages co-exist in the same directory while
in most other frameworks, pages (.jsp files or whatever is your presentation engine) and
code-behind stuff (java files ) are completely separate.
So read the documentation that comes with your framework (Spring MVC, Struts, JSF e.t.c).
Another good proposal is to use Maven Archetypes to generate a skeleton for your specific framework. Some web frameworks (such as seam) have even their own code generation tool that lays the foundations for your web project.
My only good suggestion (that is not mentioned by Yoni) for the src directory is
to make packages according to business purpose and NOT according to type/layer
That means packages for
com.mycompany.myproject.customers
com.mycompany.myproject.departments
com.mycompany.myproject.billing
com.mycompany.myproject.reports
com.mycompany.myproject.admin
and NOT
com.mycompany.myproject.entities
com.mycompany.myproject.tables
com.mycompany.myproject.graphs
com.mycompany.myproject.dialogs
com.mycompany.myproject.servlets
The second structure is too generic, tends to resolve around huge packages with unrelated stuff and is hard to maintain.
To continue my previous answer, I have many web projects. In all of them the structure under src is more or less the same. The packages are roughly separated to 3 logical layers.
First is the presentation layer, as you said, for servlets, app listeners, and helpers.
Second, there is a layer for the hibernate model/db access layer. The third layer for business logic. However, sometimes the boundary between these layers is not clear. If you are using hibernate for db access then the model is defined by hibernate classes so I put them in the same area as the dao objects. E.g. com.sample.model holds the hibernate data objects and com.sample.model.dao hold the dao objects.
If using straight jdbc (usually with Spring), then sometimes I find it more convenient to put the data objects closer to the business logic layer rather than with the db access layer.
(The rest of the stuff typically falls under the business layer).
First, the to follow the conventional structure of a popular ide, ala Eclipse, Netbeans, etc.
In Eclipse, for example, everything is arranged already with a WEB-INF and META-INF folders, so packaging and deployment is easy. Classes source code (typically under src) is automatically copied to WEB-INF/classes.
There are a few other considerations:
If you are using MVC, then it is possible that you don't need to access your JSPs directly. If so, keep the JSP source code under WEB-INF/jsp, for security reasons.
Similarly, keep custom tag files under WEB-INF/tags.
Keep javascript files in js folder, css files in style folder, etc. All folders should be at the same level as WEB-INF to mimic a real deployment.
It is good to separate your code into packages according to layers. Obviously your Hibernate daos don't need to be at the same package as your servlets.
If you end up with too many servlets in the same package, consider sub-packaging them accord to functionality, but it is nice that they have a common ancestor package - it helps with readability.
Java Web Structure
Use the Maven webapp archetype layout.
project
|-- pom.xml
`-- src
`-- main
|-- java
`-- webapp
|-- WEB-INF
| `-- web.xml
`-- index.jsp
I've included the java folder in the example here, maybe it was obvious, but it was left out in the above link for some reason.
Related
I am learning java ee related technologies (and I am relatively newbie) and try to write simple web application with Spring and Thymeleaf as frontend, and i have some problems with
modularization.
I found that it is used to pack .html filesinto WEB-INF directory for security purposes, but, as far as i guess, it means I have to put there all of my views, have controllers in this projects. I want to avoid that by having many projects for example:
web-app
admin-module
user-module
core-module
and each of them has its own, module specific controllers and views (htmls) and web-app
combines them all into single, big project.
In Thymelaf i found something like ClassLoaderTemplateResolver and got (maybe stupid idea) how to divide big project into many ones - put htmls into classpath resource directory.
By this I can ask for any html view from any module project. Does this violates some security reasons?
I would like to ask does anyone has similar problem and found proper solution how to elegantly divide html web-app project into many smaller 'context-specific' projects?
Here is my current project structure. Blue arrow idicates which view is connected to which controller:
http://prntscr.com/4tqt9m
This is my first question asked here so I hope you will treat me with some understanding.
Thank you in advance.
You might be able to merge multiple Spring and Thymeleaf modules at runtime using classpath lookup. Just make sure you give different qualified name / folder structure (eg: two files named views/index.html on different packages might cause confusing inconsistencies)
With Spring if you configure the classpath scanning properly it should take into account jar packages on the classpath.
With Thymeleaf, try setup a TemplateResolver with prefix such as classpath:/templates/, then on different modules setup a folder structure such as src/main/resources/templates/package-a/foo.html, src/main/resources/templates/package-b/foo.html. I haven't yet tried this, and not 100% sure the class loader can merge these alright.
I have recently started developing my own project from scratch using the Core of J2EE : Servlets & Jsps.
I could not evaluate whether my project folder structure is right or not. Here is my project folder structure.
The question: Is it a good sign to put my jsps outside of web-inf. If not, why is it so? If yes why?
Is there any standard folder structure convention for a J2EE web application, I know maven has brought up some standards but still, we can customize as per the requirement I believe.
What are the points to be considered while laying out the folder structure for a J2EE web application, importantly where should the Jsps, static content should go into & why?
All I can do is tell you the pros and cons to specific ideas. What follows is 100% my opinion. I don't know of any specific requirements or rules. I'm sure somebody will disagree with me.
JSP's
Let's work on whether to put JSP's in WEB-INF or not.
Pros of putting JSP's in WEB-INF:
You control how the JSP's are executed. If you want a JSP to be
parameterized and re-usable (which is really hard with a JSP anyway),
you can put them into WEB-INF and use a servlet or a Struts action
controller or some other front controller to do pre-processing and
then pass control to the JSP, passing in the right environment
context (like request attributes, any security checks, parameter
sanitation, etc.)
You can programmatically or even at a firewall or IDS level block
HTTP requests to *.jsp to reduce the likelihood of somebody uploading
a JSP to the web root and then being able to execute code as the web
server. They'd have to over-write an existing JSP. Not a huge
security gain, but it does make compromise slightly harder.
Enforces good habits, like MVC, front controller, servlet filters,
dependency injection, etc. as opposed to a big monstrous JSP that
does all the work itself and is difficult to read/maintain.
Cons of putting JSP's in WEB-INF:
You cannot access the page directly, even if it is a simple
standalone page which needs no upfront processing. This is because
files under /WEB-INF are not servable by a servlet container.
Static files
In terms of purely static files like HTML, image, stylesheet, javascript, etc. put those under the web root (my_app in your case), but NOT /WEB-INF (because it is not accessible).
Overall layout
As for the overall directory layout, it depends somewhat on your build process. I like storing everything under "src" or "source" because it makes it clear what files are generated by building and which are pure source files. main lets you separate test code like junit classes from your main source code, which is good too. But if you don't have any unit tests (oh no!), then it's a meaningless distinction.
On the other hand, if you don't manipulate the web root at all during build (like if it's all JSP and static files), then perhaps you keep it at the top level, like /webroot or /deploy and copy files in as needed, such as .class or .jar files. It is a habit of human beings (especially developers) to over-organize. A good sign of over-organizing is having lots of folders with only a single sub-folder.
What You've Shown
You've indicated that you are following a convention set by maven, so if you are already using maven, just stick with that layout. There is absolutely nothing wrong with the layout you described.
In case of WEB-INF,
If you put JSPs in WEB-INF then you won't be able to access them directly. i.e. By absolute url
Outside, WEB-INF you can directly access them
I have created a Data Access layer which is responsible to retrieve data from the database using plain SQL query. My tomcat contains two web projects. Both projects contain same copy of Data Access layer.
Web Project1 (WP1)
|----DataAccess layer
Web Project2 (WP2)
|----DataAccess layer
I would like to separate Data Access layer from web project, so I don't need to maintain multiple copies.
WP1 -- WP2
| |
DataAccess layer
Is it the best practice to make the Data Access layer as JAR file and put it inside Tomcat shared lib folder?
Thanks,
MFH
I won't say that doing so is dangerous but I definitely won't consider this solution as a "best practice" : sharing a library across all the web application will increase the probability that one of them will run into a classpath conflict.
For instance, suppose that you deploy another web application in which you're using (knowingly or not) a class that is duplicated (several classes with the same exact full qualified name), given that the shared libraries are loaded before the application specific libraries, you could end up using another class than the one expected. In the best scenarios, you'll figure it out quite easily but still that would have made you loose some time. In the worst scenario, your application won't behave as expected.
From my personal experience, I've seen this happening in the past : some applications were referring to a shared lib-1.0.jar and some others were deployed with a application-specific lib-2.0.jar (which had slightly evolved).
Besides, in your case, it won't cause a maintenance havoc : just adapt the deployment procedure from both of your web application to add the concerned library as a dependency (if you're using tools such as Maven or Ant, it's a piece of cake).
We have a couple of Java Web applications that serve different purposes (one for the public and one for internal administration) but work on the same database. We keep most of our business and database logic in a project a third project that is included in the two projects and this works well.
However, now we want to share presentation logic between the applications. (In other words we want to have the same pages controlled by the same action classes appearing in each application.)
What is the best way to accomplish this goal? Can JSPs be stored in in jars and used? Can two web apps refer to common jsps? Are there good ways for the two applications to share session data so users can go back and forth between applications?
Following can be done to achieve what you are planning:
Create a common EAR having multiple Web/EJB projects for your application. Thus all the WebApps can reside inside a common EAR file and can use common JARs kept at EAR level.
Just like a java project can depend upon another Java project, a Web Project can also depend upon other Web Projects. Hence create a common Web Project with JSPs and Utility Classes. Add this common Web Project to the Build Path of other Web Projects. They would inherit the JSPs and Java classes, and can have their custom JSPs as well.
The above would provide you the basic framework. There is no standard way for Web Apps to share data. If you want users to use common session you can use SSL or token based session maintenance. Session data from one App cannot be replicated to the other, but you can put some logic inside an EJB which can be called from both Apps there by linking them in a clean way.
The fact that you want to share presentation logic and session data betwen both application shows that these two apps should be merged in a single one, where administrators simply have more privileges than simple users.
We had similar problem. We wanted to share JSPs between several projects. JSPs can be stored in one base web project in maven war package. Then you can share this resources from base project (JSPs, CSS, Javasripts, etc.) as a maven dependency and you can override particular JSPs, CSS etc. in dependent project. It works very well for us and we don't need to e.g. repair one same JSP in many projects.
For detailed information, see: maven overlays
Whats the best practice for setting up package structures in a Java Web Application?
How would you setup your src, unit test code, etc?
You could follow maven's standard project layout. You don't have to actually use maven, but it would make the transition easier in the future (if necessary). Plus, other developers will be used to seeing that layout, since many open source projects are layed out this way,
There are a few existing resources you might check:
Properly Package Your Java Classes
Spring 2.5 Architecture
Java Tutorial - Naming a Package
SUN Naming Conventions
For what it's worth, my own personal guidelines that I tend to use are as follows:
Start with reverse domain, e.g. "com.mycompany".
Use product name, e.g. "myproduct". In some cases I tend to have common packages that do not belong to a particular product. These would end up categorized according to the functionality of these common classes, e.g. "io", "util", "ui", etc.
After this it becomes more free-form. Usually I group according to project, area of functionality, deployment, etc. For example I might have "project1", "project2", "ui", "client", etc.
A couple of other points:
It's quite common in projects I've worked on for package names to flow from the design documentation. Usually products are separated into areas of functionality or purpose already.
Don't stress too much about pushing common functionality into higher packages right away. Wait for there to be a need across projects, products, etc., and then refactor.
Watch inter-package dependencies. They're not all bad, but it can signify tight coupling between what might be separate units. There are tools that can help you keep track of this.
I would suggest creating your package structure by feature, and not by the implementation layer. A good write up on this is Java practices: Package by feature, not layer
The way I usually organise is
- src
- main
- java
- groovy
- resources
- test
- java
- groovy
- lib
- build
- test
- reports
- classes
- doc
I usually like to have the following:
bin (Binaries)
doc (Documents)
inf (Information)
lib (Libraries)
res (Resources)
src (Source)
tst (Test)
These may be considered unconventional, but I find it to be a very nice way to organize things.
The way i usually have my hierarchy of folder-
Project Name
src
bin
tests
libs
docs
One another way is to separate out the APIs, services, and entities into different packages.