How to replace file in compiled jar without affectig Tomcat redeploy - java

We are working on Liferay platform, which uses Tomcat servlet. We have deployed modules, which consist another our compiled jars. Now, we wrote simple program, that monitor our resources and replace them in webapps folder if changes detected. This works fine, but when we are trying to replace sources in compiled jars (js, html etc), then Tomcat detect changes and start redeploy.
Is there any way to replace resources in compiled jars without affecting Tomcat redeploy automatically? Our Tomcat redeploys take a lot of time, and we want to redeploy resources only on demand.

You can disable autodeployment setting Host autoDeploy attribute to false. Then you can use startup scripts, tomcat manager or REST api to redeploy.
<Host autoDeploy="false"
See https://tomcat.apache.org/tomcat-7.0-doc/deployer-howto.html#Deploying_on_a_running_Tomcat_server
You can consider also to deploy on demand using the tomcat API and providing a war. There is an Ant task available. See this example

Related

Tomcat WAR file deploy failure in Windows

I have an application running in a tomcat container in Windows environment.
When I have to update the application, the tomcat windows service is stopped, new ROOT.war file is copied in the webapps folder and tomcat service is restarted.
Sometimes it happens that the ROOT.war extraction fails and the extracted ROOT folder has only few subfolder and few files. Obviously the following application startup fails.
To solve this problem I have to stop tomcat, delete ROOT folder and run in again to let tomcat re-extract the ROOT.war again from the beginning.
I cannot understand why sometimes it happens and sometimes no. However, it makes impossibile to me to create an automatic update. It is too risky.
Do you have any idea why it can happen?
Resources are not released. So, when you try to update the existing war file, tomcat is not able to delete the older files before deployment/redeployment.
To resolve this issue, ensure that:
The application is not open/running on web browser.
You're not stuck in debug mode when you click on update.
All processes/requests are completed before redeployment.
All files/streams are closed within the code.
When all else fails, you may want to stop the application. Then update. There are ways to stop applications on tomcat using command line, batch files, etc. You can then automate the process.
If you want a more reliable way to do this, you may use jrebel or a free version of the same. There are other ways to update code. Basically, standalone tomcat is not worth anything more than a development server.
Remark: if you are updating the application while Tomcat is running you need to either:
use Tomcat Manager to deploy it,
call tryAddServiced (before Tomcat 9.0 addServiced/isServiced) before any modification to the webapps directory and removeServiced afterwards. This can be done through JMX on the bean Catalina:type=Deployer,host=<your_host_name>,
replace the WAR file (almost) atomically: e.g. deleting the old one and moving (renaming) the new one from another location on the same filesystem should work.
which prevents Tomcat from immediately deploying the application until the copy operation is finished.
To prevent the OS from locking the files in the webapps/ROOT folder you have two options:
Use antiResourceLocking="true" as already suggested by Svetlin, which basically forces Tomcat to copy webapps/ROOT to a uniquely named temporary directory before deployment (the copy will be locked, webapps/ROOT will not),
Use parallel deployment by naming your WAR files: ROOT##001.war, ROOT##002.war, etc. This is basically an explicit version of the antiResourceLocking feature with the additional advantage of letting clients transition fluently between the old and new app version.

Weblogic Auto deploy changes xhtml using intellij idea

I have a development project on ear project using jsf and primafaces. I'm using intellij 15.6 and web logic 12.1.1.0.
After I completed all the configuration on server and idea, I start server from idea, it makes and deploys the application but deploy fails.
After I do maven wls plugin undeploy, redeploy will is successfull. But when I change some xhtml files, I cannot see the changes in browser. Configuration server, update resources both them. I want to see the changes in xhtml after refresh browser or window.
Short answer is that you can't. When Weblogic loads your application it does so by staging your changes (in one way or another). Those staged files cannot be modified after loading. The best you can hope for is to leverage autodeploy, and after you build your application having a scripted deploy to the autodeploy directory. There is a possibility that if you had your project set up at the staging directory (and were not making any actual code changes) that you could tweak some files, as long as things are set up to not cache resources.
Here are the details you were looking for (note that you still need to re-compile):
Using FastSwap to speed up dev
Using FastSwap Deployment to Minimize Redeployment
Working with AutoDeploy

What happens when you run a project on a local Tomcat server in Eclipse? [duplicate]

I am making a java webapplication using eclipse and tomcat server. I want to know what happens when I run my website on Tomcat ? What are the steps Eclipse does in the background to run the application on tomcat.
This will help me understand when to switch off the server (while debugging) / when to clean the server etc.
I need to know what goes into the server so that I can get better at debugging.
Right now all I do is restart the server everytime something goes wrong. I have wasted enough time doing that. I guess I need to invest a little bit more time in understanding what happens behind the scenes.
Environment assumptions
I will assume:
target/classes is the target folder for compiled classes
src/main/webapp is the web application content folder
Project > Build Automatically option is checked
Deployment directory
Eclipse is using exploded WAR deployment - i.e. the deployed application is deployed as a folder, not a single file archive. Application files are placed and loaded from ${workspace}/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/.
Publishing
Publishing is a central process which is responsible for assembling and deploying the web application. When talking about local Tomcat, this means copying "web content, compiled classes, libraries, ..." into deployment directory (the one in .metadata).
Eclipse is able to do partial publishing - i.e. when a single resource changes (e.g. some JSP), Eclipse will publish only that single file.
By default publish process is performed automatically when some resource changes. This can be modified in server settings (double click on the server name in Servers view).
Changing static resource
If you change lets say src/main/webapp/resources/myApp/css/main.css:
upon publish the file gets copied to the deployment folder
resource is instantly available to server clients
Changing JSP file
If you change JSP file:
upon publish the file gets copied to the deployment folder
Tomcat notices that the JSP file has changed and recompiles it
changed JSP is ready to render content
Changing Java file
If you change a java source file:
the file gets compiled into target/classes
upon publish the file gets copied to the deployment folder
Tomcat notices that a class file was changed and reloads the context (i.e. web application is restarted)
You can turn of the auto-reloading feature in server settings on the Modules tab. Without auto-reloading you can still use hot swap feature, which is able to replace code in running JVM. This is possible only when method signatures are not changed.
If you want more advanced solution (i.e. not limited to changing just a method body) when it comes to reloading java changes, you should check projects like JRebel (not free).
Cleaning
Deployed application can get corrupted. It is worth noting, that when you want to clean completely compiled and published resources, you should:
Clean the compiled classes (Project > Clean... - deletes target/classes)
Clean the deployed files (Server > Clean... - deletes deployment folder)
Clean Tomcat working directory (Server > Clean Tomcat Work Directory... - deletes compiled JSPs)

Updating WLS_HOME/server/lib contents without a restart

Does anyone know how to update the content of a WebLogic Server's WLS_HOME/server/lib/ folder without having to restart it?
A colleague of mine did a deployment which involved an updated .jar file that was used by all the .ears in the user_projects directory, so he decided to place it in WLS_HOME/server/lib. Whilst the web apps he deployed to user_projects deployed ok, we noticed in the server log it was getting repeated NoClassDefFound exceptions for classes we knew were in the updated .jar - and it didn't pick up the new classes till after a restart.
I need ideally to be able to deploy new shared libraries to this /lib folder without having to restart the server as that involves an outage.
Does anyone know how to do this?
This is not possible. You should move to shared Java EE libraries if you need more flexibility. For your current situation, the only thing you can do, provided you have a clustered environment, is to do a rolling restart of the instances to avoid downtime.
From Understanding WebLogic Server Application Classloading :
WebLogic Server includes a lib subdirectory, located in the domain directory, that you can use to add one or more JAR files to the WebLogic Server system classpath when servers start up. The lib subdirectory is intended for JAR files that change infrequently and are required by all or most applications deployed in the server, or by WebLogic Server itself. For example, you might use the lib directory to store third-party utility classes that are required by all deployments in a domain. You can also use it to apply patches to WebLogic Server.
The lib directory is not recommended as a general-purpose method for sharing a JARs between one or two applications deployed in a domain, or for sharing JARs that need to be updated periodically. If you update a JAR in the lib directory, you must reboot all servers in the domain in order for applications to realize the change. If you need to share a JAR file or Java EE modules among several applications, use the Java EE libraries feature described in Creating Shared Java EE Libraries and Optional Packages.

Deploying a Spring-based WAR with its JAR dependencies externalized

I have a Spring app that has a lot of dependencies (18 megabytes of JAR files..) - Now, when I am testing on the remote Tomcat 6.0 server, I'd like to not have to upload that 19 megabytes of dependencies, and just upload the classes. Pretty simple, right?
I can't get the damn thing to work.
I'm using Eclipse 3.4, and if in Java Build Path->Order and Export I remove the export of all of the dependencies, I get a nice small WAR.
So here's what I tried:
I uploaded all of the libs to the server, and stuck them in common/lib in Tomcat. The directory didn't exist, so I created it and modified catalina.properties:
shared.loader=${catalina.home}/common/lib/*.jar
I've tried a bunch of other configs, but none worked. Restart the server, deployed war fails to start. Specifically:
SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderList$java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1
It's dying trying to load the Log4J listener, which it can't find in its classpath. The spring lib that listener is in is in common/lib.
Also - when I deploy the full 18 megabyte war, it works just fine. Everything inits and the app starts. Of course it works fine locally as well.
Oh - and I've replaced the hardcoded logging JARs with the ones out of the extras folder to allow Log4j to work.
Any help here? I have no idea why this isn't working.
"I have a Spring app that has a lot of dependencies (18 megabytes of JAR files..) - Now, when I am testing on the remote Tomcat 6.0 server, I'd like to not have to upload that 19 megabytes of dependencies, and just upload the classes. Pretty simple, right?"
I don't understand this - 19MB is not a lot. You'd be much better off just packaging a WAR and be done with it.
I recommend that you do your testing locally on your own identical Tomcat instance, get it all working, and then deploy the WAR to the remote Tomcat instance.
UPDATE: One issue I have with putting those JARs in Tomcat's /lib directory is that now every app that you deploy to that instance sees those JARs - change them for one, all are affected. If you put the JARs in each individual WEB-INF/lib, you can modify each application without affecting others. The cost is duplicate JARs and disk space, which is cheap.
Another problem if you have to migrate from devl->test->prod, now every environment has to have the identical JARs deployed in order for your app to work. Miss one and you're broken. Your app depends on having those dependencies available. If they aren't on the server you're out of luck. Keep control in your own hands and package the JARs in the WAR file.
You need to be careful externalizing the dependencies like that in a web server environment. Depending on the server there can be unexpected class-loading issues even when it seems to start up fine.
I agree with duffymo... 19MB is not really all that big... is there some reasoning behind wanting to do this? I wouldn't recommend it.
find the webapp folder
upload the files direct into the folder
for example
/path-to-tomcat/webapp/myapp/
keep the /path-to-tomcat/webapp/myapp/WEB-INF/lib folder and upload the changes to ur /path-to-tomcat/webapp/myapp/classes folder
then use tomcat manager to restart the app
I second the suggestion of sending updates directly to ${CATALINA_HOME}/webapps/<your-app> on the target server. WARs are for production deployment, but if you have a slow connection and a large WAR that's no fun.
You'll want your web app to restart after the update, of course. Tomcat in development mode will monitor a few files for changes; by default WEB-INF/web.xml is one of them, so update that along with whatever else you're updating and you should get an app restart soon. In a pinch, you can use the Manager web app to kick the app awake.
For more control and convenience, you'd eventually do well to use the Tomcat ant tasks (found near the Tomcat distribution, not included with ant!) to restart the server, and perhaps to deploy your changes as well. Takes some fiddling but this is well worth it as you'll want to re-use it for each project you do.
Is WEB-INF/lib empty?
Where is log4j.jar?
Where is spring.jar?
This looks like classloader visibility problem.
Listen to duffymo and cjstehno.
Adding jars to tomcat's is a sure recipe for disaster.
Keep your jars in your webapps directory.
It is strange that Tomcat can't find the jar files. Anyway, place all jars in the common folder (${catalina.home}/lib). (This is even worse than using the shared.folder, but it should work for you).
Of course, like others said, you shouldn't do that in your production system. I believe that is OK for a development system though - especially if you need to do extensive testing with the production system anyway.
Another note: you should only do this if you have full control of the server and you are the only one installing applications.
Why would you change the default ${shared.loader} property of tomcat?

Categories