I have two questions regarding Java web application deployment and its impact on performance.
We have an application deployed on serverA, with JSPs exploded in to one content directory (that means JSPs are not part of the WAR)
question 1: What I knew was this was an approach for development rather than any other environments. Does this exploded deployment slow down performance?
now, the content directory is cross mounted(NFS share) to another hardware, and there we run serverB, which also use the JSPs for its content.
When both serverA and serverB are running and utilizing the same content, can it slow down the performance?
Deploying JSPs in exploded form (rather than in a WAR file) won't make any difference from a performance perspective. When a WAR file is deployed, it is unpacked anyway.
Putting content (including JSPs) in an NFS mounted file system will make access to the files, and can lead to operational issues if your NFS mounts go stale at the wrong time. This will happen the first time a JSP is used, and can also happen at other times if your JSP engine is configured to periodically check for changed JSPs.
The first time any jsp is needed, it would be compiled into a servlet and stored in the web container's cache(at-least tomcat does it). Since the cache folder is not over NFS, that shouldn't affect web sevrer performance. It might be a good idea to precompile your JSPs though.
Exploding the WAR should slightly improve deploy time, but the server is going to explode the WAR file anyways when it's deployed.
As other replies pointed out, JSPs are translated into servlets and then compiled into .class bytecodes. This happens the first time a user accesses that JSP, and this will produce lag-time for the users, especially if it's a complex page. The best way around this is to precompile the JSPs.
If you application's JSPs are precompile and the compiliation feature is closed in Servlet container, it does not impacts your application's performance,because the JSPs were compiled to their .class file,and then they would be loaded by container.
Related
We deploy our product in tomcat and we are having several contexts for it, one for each client. The application is the same, we only change some parameteres in a properties.file to point the database and other specific data.
Client1 context1 http://app/context1
Client2 context2 http://app/context2
Client3 context3 http://app/context3
So we have several repeated jars, and i want to be able to update the whole instances in batch. What we are doing is keeping the jars in a tomcat classpath so our war just consists of the web.xml, properties and a context.xml and we just deploy them at will. I dont want to have the application jars inside of the war because we are having a lot of changes and we wourld be constantly packeting and eploy everithing again and again.
Will this work? Is this a good practice? Does tomcar have any tool to help us in this situation? How can i make this efficient?
Thanks
It will work and is generally a good practice because it is more efficient in terms of memory usage (shared jars are only loaded once). It can be cumbersome in development because it will require restarting tomcat whenever a shared jar is changed, since they are in a common class loader. You should place your jars in a separate directory (not in the tomcat/lib directory) and update catalina.properties to point to that directory:
shared.loader=/path/to/your/jars,/path/to/your/jars/*.jar
I have a program which permits to upload a file from somewhere into another place. This another place is the path that will be on database. Where should I upload this file:
Into c://?
Into projectSomething/ (I´m working with glassfish and in this folder it saves on C:\Users\Alvaro\Documents\glassfish-4.0\glassfish\domains\domain1\config)
Into projectSomething/src/
Answers to such questions are always (at least partially) opinion based which is bad on SO. But I'll try to give you what is considered as good practice.
As you speak of glassfish, I suppose it is a web application. For evident security reasons, you should never allow uploaded files where you could have any of your application files. You should also think that some servlet containers or Java EE servlet can display an application without exploding the war. It is clear that in such cases, you won't be able to write anything under your project root!
So where can you put it? IMHO, the best is to see that as a deployment detail and configure it in a property file, a java system property or in a environment variable and clearly identify that in your documentation. That way it is no longer your problem as a programmer. You will be able to deploy it under windows or linux (where C:/ does not exists) under a special directory under your project root if it is guaranteed that the war will be exploded and the application will have appropriate permissions on that directory.
Is there a way for a Servlet to do a hot re-deploy the webapp it is part of?
I know that I can configure Tomcat to do a hot re-deploy on changes to web.xml but I can't find any way to do the same from java code. I don't want tomcat to having to watch the web.xml for changes all the time.
I believe it can be done using JMX.
The Tomcat Manager is a web application that can be used interactively (via HTML GUI) or programmatically (via URL-based API) to deploy and manage web applications.
There is the link - http://tomcat.apache.org/tomcat-7.0-doc/deployer-howto.html
A Servlet has a life cycle that depends on the container. This is explained here
http://docs.oracle.com/javaee/5/tutorial/doc/bnafi.html
What this means is from the web.xml the container figures out a match depending on a request and if there is such a class that exists it loads it as a classloader resource. Once this has happened the instance stays loaded till the container is shutdown so replacing .class files wont actually achieve the "hot-deploy" unless you set the reloadable flag in the tomcat's context.xml
http://tomcat.apache.org/tomcat-5.5-doc/config/context.html#Common_Attributes
In any case, Tomcat or not, once a resource has been loaded by a ClassLoader changing the .class files wont exactly change the behaviour of the running jvm which you would probably know. So even deleting the class files from the file system also wont affect the running java process in ordinary situations.
However it may be possible that a servlet can start a background task that does a basic file copy of the new .class files you want to 'hot deploy' (if the context attribute 'reloadable' is true). This then forces these classes to be reloaded and so you achieve a hot deploy. So although this is out of the scope of what a servlet is designed to achieve the answer is yes.
Hope this helps.
Due project requirements, I need to create a webapp that, when executing, will allow some users to upload zip files which are like small apps and will contain .class files, resources (images, css, js, ...) and even lib files. That zip file is almost like a war file.
Any way to code it easily? AFAIK I think I know how to code the custom ClassLoader to load classes from inside the zip file ( Java - Custom ClassLoader - trying to load a class using class file full path ) and even code the resource retrieval when requested by the browser but no idea of how to execute JSP files which will be inside the zip file or load the jar lib files inside the zip file.
EDIT: the webapp must manage applications loaded, there is no way to implement this as answered below because the webapps need the "master" webapp to live. Also that "master" webapp allows versioning of applications. The user will be able to upload a new version and upgrade to it and even do a downgrade if the new version starts to fail.
There is no easy way to do this. It's a lot of work. Classloaders are very finicky beasts. Arguably the bulk of the work of creating something like Tomcat is wrangling the class loaders, the rest is just configuration. And even after all these years, we still have problems.
Tomcat, for example, is very aggressive on how it tries to unload existing webapps, using internal information of the Java class libraries to try and hunt down places for class loader leaks, etc. And despite their efforts, there's still problems.
The latest version of Glassfish has (or will have) the ability to version application deployments. You might have good luck simply hacking on Tomcats internal routing and mapping code to manage versioning.
If you're running an EJB container, you could put your core services in the EJBs and let the WARs talk to them (you could do this with web services in a generic servlet container, but many EJB containers can convert Remote semantics in to Local semantics for calls in to the same container).
You can also look at OSGI. That's another real pain to manage, but it might have enough granularity to even give you versioning, but none of your users will want to use it. Did I mention it's a real pain to manage? We do this for dynamic loading of web content and logic, but we don't version this.
If you must have everything under control of a single WAR, then your best bet is to punt on Java and instead use a scripting language. You tend to have a bit more control over the runtime of scripting environment, particularly if you DON'T let them access arbitrary Java classes.
With this you can upload whatever payload you want, handle all of the dispatch yourself to static resources and logic (which means you get to handle the versioning aspect). Use something like Velocity for your "JSP" pages, and then use Javascript or whatever for logic.
The versioned environment can be pain to pull off. If you don't care about doing it atomically, it's obviously easier. If you can afford "down time" (bring v1 offline then bring up v2), it's a lot easier. If you're uploading the full contents of each version, it's really easy. My system allowed incremental changes and had copy-on-write semantics, so it was a lot harder. But I didn't really want to upload several Gb of media for each version.
The basic takeaway is that when dealing with Classloaders, there be dragons -- nothing is easy with those and there are alternatives that actually get code in to production rather than creating scars and pissed off dragons. Using a scripting language simplifies that immensely. All the rest is dispatch, and that can be done with a filter or servlet.
You WILL get the great joy of reimplementing a solid chunk of the HTTP protocol doing this, that's always a treat as well since the servlet container doesn't really expose that functionality to you. That is, you'll want to do that if you want to be a good citizen on the web. You could always just continually shove content down the clients throat, caching and proxies be damned.
You could manually create a WAR-like structures inside your web container webapps directory and put classes, JARs and JSPs there.
Given that hot redeployment is enabled in your web container it would automatically designate a separate classloader to this new web application that it finds.
In most cases web containers consider any folder having a WEB-INF subfolder containing a valid web.xml file to be a web application. You can restrict access to this new webapp by modifying its context configuration, located in META-INF/context.xml in case of Tomcat.
Controlling hot redeployment, classloader policies etc is dependent on the type of your web container, but I hope your is not worse than Tomcat which could handle all of that.
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