I am working on project in JSF, using Tomcat 7. The application will have two parts - the presentation and the administration, main part is about the administration. What I want to do is to create something like a web library.
To have this more clear, I'll try to show structure of the project:
The main application project (let's call it admin) that is builed into WAR file.
Second project using the first one (let's call it presentation).
Presentation is using the admin WAR file.
both projects are typical JSFs - admin has pages, beans, etc.
In NetBeans, I have no problem with adding WAR file as a library, but, there are two things. The first: are all ManagedBeans in admin initialized together with presentation run, so I can use them in presentation? The second: how do I access pages from presentation that are located in admin?
Maybe I am wrong about this idea and I should use different way how to achieve this - so just tell me please.
Also, I probably will not be able to deploy two war files and run them - most of the hostings where the application will run allow deploying of one WAR file only.
Make it a common JAR instead of WAR, so that you can include it in both WARs. This way you can share managed beans and templates between both WARs. The Facelets resources can just be placed in /META-INF/resources of the JAR. The JSF artifacts like managed beans will be auto-discovered if you provide a /META-INF/faces-config.xml file.
See also:
Structure for multiple JSF projects with shared code
Related
I'm working with an application which has a modular architecture - each module is contained in a WAR file running on top of Tomcat. One of the modules allows users to extend its functionality with a request Interceptor interface, which is #Autowired into the class by Spring.
I'm working on a custom Interceptor and would like to make it available to Spring for autowiring within the module. Until now I've been building a custom version of the module's WAR which contains my interceptor, but I do not feel that this is a clean approach because the idea was to make the application easily extensible, and building my own fork for this reason seems to almost eliminate the benefits of the Interceptor interface.
I know one possibility is to crack the WAR open (it's just a ZIP archive) and drop a custom JAR in there, but that doesn't feel right either. Perhaps there is a way of adding custom JARs using Maven? Is there an industry-standard way of doing this?
I think I have at least a partial answer, everyone is welcome to provide a better one.
There is a helpful documentation page about class loading in Tomcat. It describes where classes are loaded from, snippets which are most interesting to a casual reader are reproduced below:
unpacked classes and resources in $CATALINA_BASE/lib
JAR files in $CATALINA_BASE/lib
unpacked classes and resources in $CATALINA_HOME/lib
JAR files in $CATALINA_HOME/lib
WebappX — A class loader is created for each web application that is deployed in a single Tomcat instance. All unpacked classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application, are made visible to this web application, but not to other ones.
We already having an spring web application (maven project) say webApp1 which is hosted on production and working fine but now due some business requirements we want to develop an another web application say webApp2.
So some clients demands both apps, or some either one of them. we need freedom of which module to be deployed, there can be the case where some clients don't want webApp1 so deployment package must include only webApp2 or sometimes both.
Approach 1:
Lets create another maven project and develop individually, at the time of creating deployment package use of Apache Ant can be done which will create WAR file by combining libs,views,controllers of both the applications or of one. combining web.xml,root-context.xml,servlet-context.xml may be the manual task.
Approach 2:
After searching on approach 1 I come to know about EAR (similar question https://stackoverflow.com/a/2936464/1629242).
EAR package (similar question https://stackoverflow.com/a/2936464/1629242) can be the approach, but for this do I need to convert existing application as EAR? or what changes are required in existing working web application webApp1? also how I can control which module need to be added in EAR
As for approach 2. it really depends how exactly do you host your application, what is the container. If it's Tomcat/Jetty which can be a pretty common choice, than EAR is not even an option, since they don't "understand" (can't process) EAR files.
Regarding approach 1. The 'manual' part of combining various xmls can be tedious and certainly error prone. Moreover, if you combine the xmls you won't get a real separation (at the level of classloader) between webapp1 and webapp2. After all totally different applications will be hosted in the same WAR.
So, IMHO, you should go for approach 3:
Keep webapp1 and webapp2 as different deployment units (different WARs). Keep different web.xml, spring configuration files and so forth.
Deploy these wars as 2 different files in the same container. Container will happily serve 2 different Wars. This way, spring beans, servlets, filters and so forth won't interfere between two apps at runtime. Moreover this approach can be fully automated.
Can i Have a single application with more than one web.xml files? And can two applications have a parent child relationship so that there are two web.xml?
For below servlet 3.0 you cannot.
If you are using 3.0 there is a possibility.
In JSR 315: Java Servlet 3.0 Specification, web-fragment.xml is introduced for pluggability of library jars which are packaged under WEB-INF/lib. The content of web.xml and web-fragment.xml are almost the same. One can define servlets, filters and listeners there. One can also specify metadata-complete=true in a given web-fragment.xml. In the latter case, the annotation processing of classes in that jar would be skipped. With web-fragment.xml, library jars can be self-contained and provide web related metadata information.
For sure, having two xml creates confusion and besides all, If you explain whats your exact requirement, you'l get a good/standard solution for your problem.
Can i Have a single application with more than one web.xml files?
It depends on the approach.
Approach 1
If you are working in an environment where there are certain servlets (I remember I worked on an old project where there was a Minification servlet and its purpose was to minify the JS/CSS at deploy time) and settings like e.g certain user-contraints and realms that you don't want configured on your development environment since you will be working with exploded JS/CSS and you want to bypass basic secuirty constraints configured in the application just for ease of development but you want them all tested out on QA , so it "sort of" of makes sense to have 2 different deployment descriptors configured for the same application. One in which you have only the basic settings to just deploy the application for development and on the other you have all your production settings that you want tested out on QA from A to Z.
But again, I want to make it clear that you can deploy you application using only ONE deployment descriptor.
Approach 2
Lets say you want your deployment descriptor to be broken down into small parts for plugg-ability purpose like you define your Servlets in one file and you define your securutiy constraints in other file. These files or web-fragments.xml can only work with Servlet3.0. If you look closely to how these fragments are used, at deploy time all these fragments are merged and read by the container as a "single" file (the deployment descriptor).
So in the end , we again wind up with a SINGLE deployment descriptor for the application.
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
Currently, we support many clients using the same web app, but each client has a different configuration for accessing their database, setting files etc. As the client list grows, updating the web apps is becoming increasingly arduous, and the duplication of resources is a waste of memory, file space, etc..
What we'd like to do is have a parent web app which is shared by all children web apps. Then have each child web app carry only files specific to them. When the child web app starts up, Tomcat loads the web app from the parent web app and then overrides any files defined in the child web app following an identical package structure.
We've been googling around and haven't found a ready or complete solution. Solutions we've looked at:
Tomcat common/share - could handle class and JAR files, but we don't see a way to handle static and JSP resources residing above the WEB-INF dir.
CATALINA_BASE appears to be more suited for running multiple instances of Tomcat which we'd rather avoid
A Maven possible solution, but we are not big fans of Maven, so would rather avoid it also.
Anybody have suggestions or ideas on how to solve this? If Tomcat configuration is not possible, what about a different application server (such as Glassfish) or a tool for doing dynamic file updated (such as OSGi, rsync). Would like to remove the resource duplication if possible.
Thank you.
There is no such thing as "parent" or "child" webapps. It's not part of J2EE spec and AFAIK it's not supported by any application server.
That said, your problem is twofold:
1) Having shared resources. This part is pretty easy assuming "resources" means static resources (images / CSS / javascript / etc...).
If they are truly shared (e.g. you don't need to have a separate version in some of your webapps), host them elsewhere (separate "common" webapp or put Apache in front of your Tomcat and host them there.
If you do need to have "local" versions of some of those resources you may be able to do some clever conditional URL rewriting or simply write a servlet that would check whether particular resource exists locally and, if not, take it from "common" location.
Precompile your JSPs so you only have to deal with JARs.
If your Tomcat instance only hosts your apps, you can indeed put your JARs in shared (or lib in the latest version); otherwise you can deploy them with each application .
2) Simplifying deployment. I'm not really sure what the big problem is here... It's rather trivial to write an Ant (batch, shell, what have you) script that would assemble and deploy WARs based on "common" and "per-app" directory structures.
Alternatively, you may want to take a look at using JNDI to severely reduce the number of files that have to be deployed (in theory, to a single context.xml for each application).
You can build parent-child hierarchy if you use Spring at your web-apps - Using a shared parent application context in a multi-war Spring application.
I.e. you can define all shared stuff at the 'parent' context and have 'child' contexts just to use it.
If all you had was setting file and configuration changes you could manage these through the context.xml and then you can point the docBase of each application context at a common directory for all the applications to share the same source.
the drawback to this is changes to the application will require a tomcat restart.
This does not however solve your problem if you want to override logic.
A option that I am exploring for a similar scenario is to move the client custom portion into ajax widgets / gadgets. Then have it be part of the configuration files to tell the application which version of the gadget to pull for which client.
you can review documentation for having applications share a docbase here http://tomcat.apache.org/tomcat-5.5-doc/config/context.html