I have a situation wherein i have multiple war files with 90% code base same (controllers, html files etc).
They have some custom code for each along with different configurations.
Currently these projects are nothing but a copy of each others (with minor tweaks and config changes).
How should i approach this for creating a single module/jar from where these multiple wars can be created with minim code(their respective changes) in the war modules.
So, the common module will have all the code along with the html files and in each war module i'll just override/provide different implementation.
I am using Gradle for build.
Using Java, Spring.
Say, I have a Project FOO.
It's a web project with java classes, html, properties and configuration (beans, persistence) files and web.xml file.
I have another project BOO.
which is a copy of FOO but there are some property changes, some code changes to existing implementation and some new code of it's own.
I dont want to keep duplicate code in BOO, BOO should ideally have the new code and the changed implementation.
This is what i want to achieve.
I cant post the code as its a big project.
Hope this makes it clear.
This is perfectly a refactoring project. Your main concentration area are all config files and default servlet and default html pages. As your project codes are not available here we can not directly advice you any more. You have to carefully check configuration of each project and find a solution how you can club together all the config files. Especially concentrate in spring-bean.xml and web.xml. You must be very careful else it will take ages for you to merge all the application. Good luck.
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.
Typically on a Java project using Maven, you place client-side source files in src/main/webapp. This directory includes your html, css, scripts, images, etc.
However, many grunt projects tend to place these files on the root. It's as if Grunt was designed with the idea that your project is the client-side application, not part of a large server-side project, such as using Java with Spring.
Given a Java project using Maven, where would be the best place to put your web-related source files?
Do you place them in src/main/webapp?
Do you make another directory altogether, such as src/web, and then on a build, copy everything to src/main/webapp?
My goal is to make the client-side build tool as transparent as possible. I guess the ideal case is to simply work from src/main/webapp as I have been doing all along - this is pretty unobtrusive to the way my project is currently setup.
However, if I work from src/main/webapp, I know that I will need to distinguish between src and build directories somehow anyway. I'm sure my html files can stay where they are, but there's definitely going to be a conflict of interest here with javascript and css files, and maybe images too.
Does it make sense to literally have a 100% separate source folder from src/main/webapp? Is there a way to do continuous building/copying/syncing of the application as you modify files, from src/web to src/main/webapp? Will this be inconvenient and cause frustrations and problems? Is it slow?
I would like any advice on the subject. Thank you.
Option 1: Put UI resources in src/main/webapp:
This is a quick-n-dirty solution popular on Github. It helps to keep example projects small and concise. In this case, usually people put the package.json, bower.json, Gruntfile.js and .bowerrc in the maven project's root directory, where the .bowerrc says to install components into src/main/webapp/bower_components.
If you have a task that minifies/transforms resources, the transformed resources can go to a new directory like src/main/webapp/dist. Then use something like grunt-usemin to make your app use the resources in the dist directory.
If your application will use a security framework (like, say, Spring Security), you might want all your resources in src/main/webapp so that the security framework can regulate access to those resources. However you can still achieve this using Option 2 by having a grunt task that copies the necessary resources into src/main/webapp.
Pros
Common approach on GitHub. Keeps everything in one project.
Cons
The version of files getting served by your server is a copy of those in src/main/webapp, so changing a file in src/main/webapp isn't immediately reflected in your deployed app. To get hot reloading, you need to use something like grunt-contrib-* stuff.
Frontend and backend code is all mixed together. Harder for two different teams to work on the code base.
Option 2: Put UI resources in a separate project:
You can achieve better project organization by keeping the UI and backend in completely separate projects. In this case the UI and the maven project would likely be sibling directories.
Then when deploying to a server, you either:
deploy both projects separately (call them myproject-ui and myproject-services). The javascript in myproject-ui makes RESTful service calls to myproject-services/**.
Use a grunt task to copy necessary resources to src/main/webapp, then deploy your (one) project.
Pros
The backend and the frontend are separated as much as possible
The frontend maintains the workflow and directory structure found in most client-side example apps, as you mentioned
"Deploying" the UI is a simple matter of creating a symlink from your server's deployment directory to you UI source code. Changing any UI code is automatically reflected in the deployed app.
You can have several different UIs deployed simultaneously (maybe you have myproject-admin-ui and myproject-user-ui). You could hit either one simply by visiting
http://localhost:8080/myproject-admin-ui
http://localhost:8080/myproject-user-ui
We are having a debate at my office around what can and cannot go in a JAR file. It has been suggested that it is poor form to have anything that is not a .class file go into a JAR. We currently have some XML configurations for Ibatis/etc, some property files.. the usual. However, there is a push to extract all such files from JARs and put them onto the local file system of each deployment machine. Does this sound reasonable?
it is poor form to have anything that
is not a .class file go into a JAR
That is nonsense. It is in fact very good form to put resources like icons and other data files that user used by the code into the JAR together with the code. This is what the getResource() and getResourceAsStream() methods of Class and ClassLoader are for, and it makes for much more robust applications than messing around with resource paths manually.
However, config files are possibly a different matter. If they're meant to be changed during or after deployment, then having them inside a JAR file is rather inconvenient, and having them in a separate directory is preferable.
If you make changes in a configuration file inside a JAR (even without altering any line of Java code), the whole JAR needs to be rebuilt and redeployed. Does this sound reasonable?
It's absolutely OK to put non-class files in a JAR file, especially resources that the application needs (images, localized strings, etc.) Knowing this, you must decide which scenario fits your situation:
If the configuration is fixed and will only change when a new JAR file is deployed, put it in the JAR.
If the configuration must be altered, either manually or by the application, store it on the filesystem.
If you choose the latter, note that it's good practice to include a default configuration in the JAR file to handle the case when the external configuration file is missing. The default can be loaded directly from the JAR or copied to the filesystem to become the new editable configuration.
It does not sound reasonable to me. I believe, that some application's configuration should be in jar file. Such things as ORM mappings, spring config, custom spring namespace XSD, other XSDs, etc.. should be in most cases in jar. It's important part of deployment artifact.
The fact, that it's not class file, does not mean, that it should be taken out of jar just because it's theoretically can be modified without building a new jar. Can you imagine a modification of *.hbm.xml in production? for me it sounds very scary.
I think some configuration, like spring xml, is meant in most cases to better organize your application and dependencies, but not to change them at runtime in production.
Do you want or expect them to be changed without a new release of the code? Then you need to extract them.
If the answer to the question in no than you shouldn't extract them, as it would allow support to tinker around with them without going through the release process. (Of course this is also possible if they are in the JAR but slightly less tempting.)
Update: But since you mentioned multiple deployment machines, there's a third option: extract them and place them in a commonly accessible area on a network drive. Manually editable config files which are replicated on several machines (but should be identical) are notorious for getting out of sync.
ORM tools (such as Hibernate or IBatis) are not really supposed to be modified once the application is deployed. So, no, I would say that it doesn't make sense for that kind of files.
Depending on your requirements, application-wide configuration files can be placed outside the Jar/War so that they can be modified without having to rebuild the jar.
Do keep in mind that modifying application parameters in production is, imho, a bad practice. Changes should be tested first in some pre-production environment.
I have an app written with GWT and GAE where every supported city has its own app. Clearly this is not the best way to manage the map so I want to merge them all into one app. Currently my app is at the urls sub1.myapp.com, sub2.myapp.com, sub3.myapp.com, etc, and I want them to be at myapp.com/sub1 ,myapp.com/sub2, etc. All the supported cities share common code, so I'm going to put all the that code in one module, and have a different module for each piece of unique code block. Is this going about it the right way? How will the different modules interact?
Also, I currently have JSPs at sub1.myapp.com/listofsomesort and I would like to move these to myapp.com/sub1/listofsomesort. Is there a simple way to accomplish this?
By making a module with EntryPoint for each old application, in one and the same application. Each module has one 'welcome page' which you can put in different directories. All the shared code can go into another module. The shared code can be used by the inherit setting in other modules.
The only thing I bumped into was that when you deploy to GAE, ALL modules should have an entry point, also the library modules. I solved it by adding a dummy EntryPoint to them, that does nothing, but still searching for a better solution. See my question at How to deploy GWT Project containing GWT modules without entry points with Eclipse GAE plugin?.
This seems like the job for Code Splitting :) It might require some changes in the structure of your code, though - depends how tightly coupled your classes are. A compile report should tell you if your code splits up nicely, or if not, where the connections are.
Is it possible, by using ANT, to create 1 war-file out of two separate eclipse java web application projects? Besides from just copying the right files to the right places i would have to be able two create one single web.xml. Also some other files that exists in both projects should be united into one file.
Thanks
Pich
If you want to package multiple web applications together, the standard format for that is an EAR file. http://en.wikipedia.org/wiki/EAR_(file_format)
Ant doesn't care about eclipse. It can grab stuff from anywhere.
But taking 2 separate web.xml and combining into 1 file.. not sure you can automatically do that. Too many variables with how that would happen.
What you COULD do is:
Have project 1 all by itself in
eclipse
Have project 2 all by
itself in eclipse
Have common
stuff like the super web.xml (that
you make by hand) in a third project
3
Have ant pull the right stuff
from all over and make a war.
Sounds like a lot of work though. Why do you have 2 separate web.xml if they are going to the same war? Why not just make 1 big project?
It is easy if there are no duplicate files. Then just unzip them on top of each other, and zip them back to a new WAR file.
If there are duplicates you need to determine what information goes in the resulting file. For merging web.xml files, the easiest is most likely by using an XML capable transformation tool. The typical choice is XSLT, and there is an XSLT engine available in Java 1.4 and newer.
The question is, however, if this can be fully automated or you need to have the authors of either WAR files know about the other (write snippets, etc). Please provide more details.