Change web.xml after deployment - deployment

Is it advisable to change web.xml (or, in fact, any other file) in app server after the deployment? Do ALL app servers expose their deployment/directory structure?
I would prefer making changes locally, re-building the war (or .ear, etc.), and re-deploying the application.

Regarding your first question, it depends on the type of the resource. For a classpath resource, you can override the file in any directory that has a higher priority in the class loading mechanism of your application server ($CATALINA_HOME/lib for instance if you're using Tomcat). For an xml file, like web.xml, you can declare an external entity in the packaged file with an absolute path, but you have to be sure that the file will be present on the target server. For instance, your packaged web.xml could look like that:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE document [
<!ENTITY webEntity SYSTEM 'C:\Temp\web.xml'>
]>
&webEntity;
So the actual content of the web.xml would be the content of the file C:\Temp\web.xml.
In short, there is no official way to do it but there are tricks. I guess, what people do is to produce a custom package for each production site. There are multiple ways to automate this with Maven like war overlay or classifiers. Here is an interesting link.
Regarding your second question, I would not rely on this assumption. It's quite straight-forward to modify an exploded resource on a Tomcat server but it's is not that simple on a JBoss AS.

Related

Make per-context JNDI variable available to Tomcat in Eclipse

I'm using Tomcat 8.5.6 inside Eclipse 4.6.1. I have my web-app project/context foo, which has a JAX-RS (using RESTEasy 3.1.0.CR3) endpoint of bar, so I can fire up Tomcat inside Eclipse and access:
http://localhost:8080/foo/bar
I have a variable named foobar which I want to access inside my JAX-RS implementation using JNDI:
final String foobar = (String) new InitialContext().lookup("java:comp/env/foobar");
I plan on deploying the produced WAR in production using Tomcat autodeploy. I want to configure the foobar variable for Tomcat externally to the WAR. How can I do that so that I can test it in Eclipse?
After a lot of reading, I found what I thought to be the $CATALINA_HOME of Eclipse: …\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\. So I created a context file for foo at …\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\conf\Catalina\localhost\foo.xml to correspond to my project/context, and put the following inside it:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="foobar" type="java.lang.String" value="123"/>
</Context>
Yes, I know that Eclipse erases this directory whenever I rebuild. But after building, I saved to file at least want to see if it works. It doesn't. I get an error:
javax.naming.NameNotFoundException: Name [foobar] is not bound in this Context. Unable to find [foobar].
I want to at least get it working so I can know how to do this in production, and worry later about the context file deletion thing in Eclipse. So what did I do wrong? Why can't Tomcat in Eclipse find this JNDI variable?
Note: I am not using a web.xml file and have no desire to do so; besides, this variable should be defined outside the WAR in the production deployment.
Update: The good news is that (on Windows 10 Professional Anniversary Edition 64-bit) using the same Tomcat but in standalone mode, I put the same foobar.xml file inside the standalone Tomcat's conf\Catalina\localhost\foo.xml, and my JAX-RS application picked it up just fine. So how can I define a JNDI variable in Tomcat inside Eclipse for testing?
It appears that in order to get Eclipse+Tomcat to recognize the per-module context files, you have to go into the server configuration (double-click on the server) and turn on the Publish module contexts to separate XML files. This way Tomcat will use the specific context XML file you created. Otherwise it apparently puts them in conf/server.xml and ignores the context-specific file you created.
There is still the problem that Eclipse regenerates this file each time you do a rebuild, destroying whatever JNDI variables you placed there. I'm trying to get the workaround in https://stackoverflow.com/a/22380248/421049 to work, but not yet succeeding. Anyone have any better ideas?
At least I'm able to reproduce a production environment now --- albeit temporarily, until the next rebuild.
Your link to Markus' answer on https://stackoverflow.com/a/22380248/1794485 allowed me to get this working, or at least as described in his workaround. But the remaining problem to solve was ordering.
As he said, you can workaround this by having a local copy of the META-INF/context.xml somewhere else, and adding this folder to the Deployment Assembly in the project properties of the Eclipse project.
This didn't pick up for me initially though. It looks like that while the Deployment Assembly in the properties shows as sorted by name, in fact it has an order like any other path. When I then removed the src/main/webapp entry (so the one containing the normal META-INF/context.xml) and added it back in, this effectively moved it down the pecking order. The next Tomcat deploy and startup in Eclipse finally put my preferred copy of META-INF/context.xml in .metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\myapp\META-INF
If in doubt about the true sequence of that Deployment Assembly path, have a look under your Eclipse project on the file system - at .settings\org.eclipse.wst.common.component.

can OFBiz be configured to work as a single monolithic webapp?

OFBiz by default works as a collections of small webapps each with its own front controller. OFBiz webapps typically depend on a lot of common modules. Typically, modules under specialpurpose or hot-deploy would end up depending on pretty much all of the modules under framework and applications... with the embedded container, all libraries go into the catalina shared library class loader but if ofbiz needs to be deployed in a different container, there is simply no easy way. the only options i believe are
package ofbiz as an EAR with a EAR/lib or EAR/APP-INF/lib so that all webapps have access to a common set of EAR level classpath resources.. typically each modules's config, lib and the all important ofbiz-$module.jar
each webapp packages each of the required jars into its own WEB-INF/lib.. too much duplication and also increases the filesystem footprint in a sense
use the application system classpath in lieu of catalina shared.lib folder - which means the JVM has to be dedicated to ofbiz as its jars would otherwise interfere with other sibling deployments and potentially even with the container itself, typically things such as XML, XSL, STAX apis etc..
given that ofbiz load most of the resources using the filesystem (ofbiz.home + component://) resulution. What the webapp really needs access to in a convential servlet context kind of way is the
controller.xml
classpath resources - across the various ofbiz-$module.jar in shared.lib. typically, each modules's config, lib and the all important ofbiz-$module.jar
imported (component://) webapp resources like other controller.xml for various modules. most importantly the framework/common/webcommon/WEB-INF/controller.xml that provides the boiler plate security implementation like checkLogin and autoLogin....
I was wondering if we could somehow package multiple webapps into a single monolithic webapp using front controller namespacing so that the war maps to a single root content like say / (ROOT on tomcat) and /content, /webtools, /catalog, /ecommerce etc. are mere URL namespaces/subcontexts rather than separate webapps. framework/common/webcommon/WEB-INF/controller.xml could become the root controller for / (ROOT in tomcat) and provide checkLogin, autoLogin etc to all webapps without each controller having to import that controller.xml
This would allow us to simply the deployment model when we would want to move to other containers like say weblogic, jboss et al where we would be better of building a single webapp with all of its dependencies neatly packaged into its WEB-INF/lib such that it could coexist with other deployments in the same container without interfering with their dependencices and their versions...
I believe struts had this kind of modular namespacing where there could be a root level struts.xml (our case controller.xml) and each module would be a folder with its own module/struts.xml or module/struts-module.xml etc...
i personally feel this would be helpful.. i have not thought enough about the downsides. there could be many? i honestly don't know. I have not given enough thought to themes either.. developers clearly would not like to see any change in the way code is laid out or organized.. so with some minor? :) changes in the core MVC code in the framework, we could potentially support this kind of deployment using a simple ant build script that stages candidate webapps into a merged monolithic webapp...
i was hoping to see a debate on the merits of this idea... i would even be willing to invest some time into making this work if i get some direction and inputs..
Have you considered using chef to deploy Ofbiz instead?
I wrote the following cookbook to demonstrate how it could work:
https://github.com/myspotontheweb/chef-ofbiz
This is a difficult part of how Apache OFBiz is architected. Using EAR files works okay, but shared classpath resources in an EAR file are app-server specific, and you have to deploy in a container that supports EAR files which limits choices.
One of the limitations is the flat namespace for requests in the controller.xml files, and what you describe would be the best way to handle that (use a different ControlServlet mount point for each OFBiz component app). Doing so may require some code changes for the URL writing (the #ofbizUrl FTL tag and the underlying code used elsewhere). It would also require a bit of work to write an ant target or something to build the WAR file, pulling in all the webapps from the various components (or just those desired), writing a combined web.xml file, etc, etc.
This is a recognized issue with OFBiz, and isn't a problem for most deployments, but does make it more difficult to scale down or host along with other applications. You can add other webapps through OFBiz components to host them on the embedded servlet container, but I don't imagine that is what you are looking for.
One of the issues with making this and many similar changes in OFBiz is the large code base, large user base, and the somewhat large committer group with diverse opinions on things like this. For these and other reasons a lot of the ideas for improving OFBiz can't be easily realized there, and that is why I started the Moqui Framework project in 2010.
Moqui deploys with a single WAR file, and can have an external or embedded runtime directory to make it easy to deploy on WAR hosting services such as AWS ElasticBeanstalk, as well as dropping in to servlet containers such as Apache Tomcat. The WAR file is also an executable JAR file using an embedded Winstone servlet container for easier development and automated testing. There are details about running and deploying Moqui here:
http://www.moqui.org/framework/docs/RunDeploy.html
BTW, this is one of hundreds of ideas for improvements to OFBiz that made it into Moqui Framework and the separate project with data model and services (Mantle Business Artifacts). There is general information about it here:
http://www.moqui.org/

URL mapping of servlets and JSP files with Tomcat and Eclipse

I have a web application project in Eclipse that is configured to deploy to a local Tomcat server. Let's call the web application Blah. Here are two questions -- I must be missing something very simple, but I can't find an easy way to change these settings within Eclipse without fiddling with the Tomcat configuration files.
1.
When the application is deployed, the URL I can use to browse to some servlet/JSP is localhost:port/Blah/servlet. I would like to get rid of the Blah prefix.
2.
I would like to set up redirects for some JSP files to "hide" the .jsp extension. For example, I'd like localhost:port/login to be served by localhost:port/login.jsp, preferably without the browser seeing a 30x redirect status code.
3.
I would like to set the default URL, i.e. localhost:port/, to redirect to a particular JSP or servlet (again, preferably without issuing a redirect status code).
Any help, including links to relevant resources, would be greatly appreciated. Please note that I am looking for a way to configure these things from within Eclipse, if possible. (If not possible, I would like to do the minimal amount of changes to the scary Tomcat XML files.)
This means that you need to deploy your application as the root application. It's easily done by naming your war file ROOT.WAR (or your exploded war directory ROOT), or by defining a context for your web app with an empty string as the path attribute.
Then you don't want a redirect, but a forward. Or you simply want to map the JSP (which IS a servlet) to a given path. Define a servlet and a servlet mapping in the web.xml file, as you would for a servlet class, but use <jsp-file> instead of <servlet-class>.
This is done using the <welcome-file-list> element in the web.xml.

Place GWT application on Jetty

Can someone help me to place my GWT application on Jetty. I am not using maven. I have libraries in my build path.
First I am taking the war folder already exploded and copy it in jetty/webapps, then in folder context.
I have placed a folde named BiddingSystem in folder web apps, it is an already exploded folder and not a .war file
In folder jetty/context, there is a file test.xml
I am renaming the file to BiddingSystem.xml
and also editing content of BiddingSystem.xml, finally the content of BiddingSystem.xml is
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<set name="contextPath">/BiddingSystem</set>
<set name="war"><systemproperty name="jetty.home" default="."/>/webapps/BiddingSystem</set>
</configure>
I am getting this error:
to deploy GWT app on Jetty, you often do not need to configure anything.
Copy your 'war' folder (which is created in your eclipse project by GWT) to JETTY_HOME\webapps
change the name 'war' to anything you like for examples "StockWatcher" so you will have JETTY_HOME\webapps\StockWatcher. Now start jetty server and try http://localhost:8080/StockWatcher on your Chrome :)
When GWT is compiled it creates just javascript and html (plus resources like css/jpg/etc..). GWT jars and your Java classes are only used during build process and NOT needed during deployment.
So, you just need to copy contents of you /war directory to your Jetty deployment directory.
There is a .html file which is called host page. It links to all other javascript and css pages needed. This is the entry point to your app. Just open this page in your browser.
It seems that you are new to GWT so there are a few basic things you need to know:
GWT is a client-side technology. You write Java code which is compiled to javascript that then runs inside browser. In this sense GWT is more related to javascript libraries (jQuery,..) than classic page-by-page web frameworks (jsf, Ror, php).
GWT app runs inside a single HTML page (called a host page). This page ever reloads. Look at Gmail to see how this works (though Gmail itself is not written in GWT) .
GWT is NOT a server side technology. You can use any technology on the server side (php, RoR, anything) that supports REST.
GWT can talk to server via AJAX. The data exchange format can be JSON or XML. Backend can be any technology that can produce REST-style JSON or XML content. If you have Java backend you can use GWT-RPC which adds some more capabilities over AJAX/JSON.

Deployment of Web Application to a Running Tomcat

I would like to collect some best-practices on deployment of a web-application to a running Tomcat. Not long ago I had to describe the deployment process of our web-application and the process appeared rather confusing.
Say, we have an application in a WAR file (foo.war) correctly configured and not requiring additional configuration. In this case, the deployment process is rather easy:
Copy the foo.war file to the $CATALINA_HOME/webapps directory. If the application starts correctly, the application will automatically deploy to $CATALINA_HOME/webapps/foo directory.
To undeploy the application:
Remove the foo.war file from the $CATALINA_HOME/webapps. If the application unloads correctly, it will be unloaded and the $CATALINA_HOME/webapps/foo will be removed.
Now I want to override some context parameters in my running application. Having read the docs, all I need to do:
Create a context.xml file called foo.xml
Copy the file to the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory.
Unfortunately, that did not work: the application would not restart. Empirically, we found out that the only working solution is when the war file is deployed to a location outside the $CATALINA_HOME/webapps.
Besides, the default values of the configurable context parameters in the WAR file should be specified in the web.xml, since context.xml in the WAR file is not read when there is a context.xml outside.
Here is an easy example of the foo.xml:
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/path-to-deployment-directory/foo.war">
<Parameter name="myparam" value="newvalue" override="false"/>
</Context>
Be sure to specify override=false for the parameter if you want the 'newvalue' to override the value specified in the WAR's web.xml. This was not obvious for us.
Thus, to deploy an aplication to a running Tomcat:
Create a context.xml file called foo.xml
Copy the file to the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory.
Copy the foo.war to the location specified in the docBase of the foo.xml; the application will deploy automatically.
To apply new context parameters:
Add the parameter values to the foo.xml and save the file; the application will re-deploy automatically.
To undeploy the application:
Remove the foo.xml from the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory
Note that removing the foo.war will also work, but will remove the foo.xml as well.
By now, I have the following questions:
Is it a best-practice at all to deploy a web-application without stopping the tomcat? I heard an opinion that deployment to a running tomcat is never needed since people run each application in a separate tomcat.
Is it a good idea to copy WAR files to $CATALINA_HOME/webapps or they should better be kept in a separate location?
How can I configure an application deployed to $CATALINA_HOME/webapps
Why there is no INFO line in the catalina.out for deployment of an application and there is one for undeployment? Is it configurable?
On question (1), Tomcat works great for deploying servlets into a running server. There may be concerns w.r.t. security or possibly D.O.S. or provisioning reasons why you would have separate server instances.
You have the flexibility to do either way, but it is often more convenient to deploy to an already running server. This is a BUILT-IN feature in the servlet architecture. :)
For (2), again it is at your discretion where you you want to put WARs. It sounds like you already have it configured a non-standard (non-default I should say) way. Check your server.xml file for the settings in your server instance(s). Check for attributes like unpackWARs and autoDeploy.
For (3) and (4), plus your (1,2) questions, it might be a good idea to consult the Tomcat docs for your version of Tomcat on its deployment model. You should be able to use the same docs to figure out how your server has been configured.
See Tomcat Web Application Deployment in the Tomcat manual, adjusting for your version of Tomcat.
One solution would be to use the manager application. If you decide that is safe to use it, then you can easily deploy, start, stop and undeploy applications:
http://localhost:8080/manager/deploy?path=[context_path]
http://localhost:8080/manager/start?path=[context_path]
http://localhost:8080/manager/stop?path=[context_path]
http://localhost:8080/manager/undeploy?path=[context_path]
There are ant tasks that can help you with these.
I am guessing, but do not know for sure, that stopping and starting an application will make it reread the context.xml.
Regarding your second question, I believe it is better for maintenance reasons to keep the war files in the webapps directory.