I use eclipse + tomcat + maven.
When I deploy my project to Tomcat, the following entry gets added to the server.xml of the tomcat configuration:
<Context docBase="C:\ws_eclipse\ws\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\MyApp" path="/myApp" reloadable="true" source="org.eclipse.jst.jee.server:MyApp"/>
What I actually want is to add an environment variable so that the context looks like this:
<Context docBase="C:\ws_eclipse\ws\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\wtpwebapps\MyApp" path="/myApp" reloadable="true" source="org.eclipse.jst.jee.server:MyApp">
<Environment name="config.file" type="java.lang.String" value="C:/test/config.xml" />
</Context>
I tried adding it as an environment variable in eclipse run configuration, but when I deployed the application on tomcat, the context does not include the environment variable.
You could add a context.xml file in the META-INF directory of your webapp. The content of this file may look like:
<Context>
<Parameter name="config.file" value="C:/test/config.xml"/>
</Context>
This has the same effect as defining a <context-param/> in your web.xml. Use ServletContext.getInitParameter("config.file") to retrieve it's value as a String.
You may use Environment as well, but it's probably overkill (You just need a String anyway, I think).
See http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
Setting it in application launch configuration is the best way, you might want to verify what you did at here - Creating a Java application launch configuration
HTH
Related
I do have a tomcat server where three apps are running.
For one of them i need to pass the system variables (-D) like spring active profiles and some other project specific variables.
I've read the documentation and one of the solutions was to create a context.xml (as far as i understood it has to have the same name as the war file) at $CATALINA_BASE/localhost/ folder
I've tried to do it like that
<Context>
<Parameter name="spring.profiles.active" value="profile"
override="false"/>
<Parameter name="variable" value="value"
override="false"/>
</Context>
But after the tomcat is restarted seems that the app is not starting and nothing actually happens.
Since there are 3 apps on tomcat server i'm unable to use setenv.sh and the parameters have to be passed specifically for this project.
Do you have any idea on what am i doing wrong and how to pass the system variables to a specific application on tomcat server?
Thanks for your suggestions
My mistake was that i've named the file context.xml and not the applicationName.xml
The file itself looks like:
<Context>
<Environment name="spring.profiles.active" value="profile" type="java.lang.String" override="false" />
I would like to have an additional classpath directory in tomcat 7, like what can be done by adding ${catalina.home}/mydir in catalina.properties, but specific to an application (war).
I would also like this setting to be outside the war (I found this SO question, but the configuration is within the war).
I my case, it is to have two environments (say integration and QA) on the same container, with different configurations. I wish to keep the artifacts environment agnostic, so not changing the path to the configuration files (properties, logback, ...).
Can this be done ? How ?
Thank you.
VirtualWebappLoader https://stackoverflow.com/a/6410589/173149:
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/websandbox">
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/usr/.../*.jar;/usr/.../*.jar"/>
</Context>
This config can be placed in $CATALINF_ROOT/config/Catalina/localhost/$PREFIX.xml where $PREFIXis context of your application. Use ROOT to place at /
My context.xml (in META_INF) folder looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="MY_CONTEXT_NAME" docBase="${catalina.home}/webapps/MY_APP_NAME"
debug="0" privileged="true">
</Context>
The problem is, context.xml is getting copied to the CATALINA_HOME> conf>Catalina>localhost folder when I deploy my application war via tomcat manager. However, it is somehow still deploying from default context, that is , app_war_name.
Earlier, it was not even getting copied to localhost folder, I removed the default context.xml form tomcat 6.0>conf folder. After that, the file is at least getting copied. However, the deployment is not happening from the explicit context.xml.
My server.xml host entry looks like this :
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="false"
xmlValidation="false" xmlNamespaceAware="false" >
</Host>
Read the documentation for the path element of the Context element. It states quite clearly
This attribute must only be used when statically defining a Context in
server.xml. In all other circumstances, the path will be inferred from
the filenames used for either the .xml context file or the docBase.
Even when statically defining a Context in server.xml, this attribute
must not be set unless either the docBase is not located under the
Host's appBase or both deployOnStartup and autoDeploy are false. If
this rule is not followed, double deployment is likely to result.
Then read the documentation for the docBase element.
The value of this field must not be set unless the Context element is
defined in server.xml or the docBase is not located under the Host's
appBase.
if you deploy again with new context or changed context you need to un-deploy first/ or remove context.xml from conf/.../localhost/yourapp.xml
I am trying to use the crossContext feature in Tomcat so that I need to set <Context crossContext="true"> in the context.xml file located in mypath\apache-tomcat-7.0.41\conf folder.
However I find that every time I restart tomcat it will restore to its original value then I have to modify that again. I want to know if there is a way to avoid this so that I do not need to modify the context.xml file every time I restart Tomcat?
Thanks in advance!
<Context crossContext="true">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Manager pathname="" />
</Context>
above is the code I am using...
According the the answer in this question [link] Tomcat context.xml files, is there a hiearchy?
I figured out the way to solve this problem. Just create the context.xml file in the location mypath\apache-tomcat-7.0.41\conf\Catalina\localhost and add in <Context crossContext="true"> </Context> then you are done.
You need to undeploy your web application and then re-deploy it. Tomcat is re-using the context.xml file you provided on initial deployment, which you can find in CATALINA_BASE/conf/[engine]/[host]/[context].xml. The changes you are making to your own context.xml are probably being completely ignored.
I have a web application that relies on some resources and parameters to be configured after it is installed, like a JDBC connection.
What I have come up with is providing a META-INF/context.xml which is copied into [engine-name]/[server-name]/[app-name].xml by Tomcat when I deploy the application. This way all I am providing is a war file that can be copied into the appBase folder (webapps).
Tomcat's documentation says if there is such a file it won't be overwritten which is really great, since the changes made after deployment won't be lost.
But there is a subtle issue here:
Since we deploy the application by copying into webapps directory, Tomcat will first uninstall the existing application as well as the configuration file. This way the configuration file will be lost / overwritten which is not desirable.
Tomcat won't modify this behaviour as far as I know.
The question is:
Is there a way to work around this issue by installing the application in a way that Tomcat won't remove the existing configuration file.
Or, is there a better way of packaging the application?
Please note that we don't want to set autoDeploy to false and we cannot use human intervention for the installation (which rules out using Tomcat Manager web application).
If I get the configuration file out of .war file and copy it separately as [engine-name]/[server-name]/[app-name].xml, Tomcat will still associate it with my application and remove it once I copy a new .war file.
Another assumption is: We don't know in advance the values to the configuration. We will only provide a sample configuration (a placeholder, if you wish) while actual configuration will be performed at some time later (not necessarily in the installation time).
Thanks
The solution is simple: don't put configuration in your context.xml.
Here is a solution that we use (which works well for a number of diverse external customers):
We have a single war which will be used in multiple environments, webapp.war. We have three environments, development, integration and production. Integration and production are at the customer site. We don't know passwords and file paths for the client integration and production sites.
We use a combination of two things: JNDI lookup for database stuff and external properties files.
In the context.xml that is delivered in the war, we have a ResourceLink
<ResourceLink name="jdbc/webapp"
global="uk.co.farwell.webapp.datasource.MySqlDataSource" />
This gives a reference to a globally defined data source, which is defined in the server.xml for Tomcat.
<Resource auth="Container"
driverClassName="com.mysql.jdbc.Driver"
name="uk.co.farwell.webapp.datasource.MySqlDataSource"
password="xxx" url="xxx" username="fff" />
So the database details can be changed by editing the server.xml without changing the webapp.war. Crucially, this only needs to be done once for each server, not at redeploy.
In our spring configuration, to define the dataSource we have:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/webapp" />
For other properties, we have a global application.properties file which is delivered along with the webapp.war, but is not part of the war. This is referenced by a -D on the command line to start Tomcat. -Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff". We pick up the definition and read the properties file. The database stuff could be done this way as well, but we'd lose the pooling done by Tomcat.
Another thing: we don't have to rebuild if servers are moved, or if machines are changed for some reason. This is a matter for the customer and their infrastructure people.
I managed to resolve this issue somehow.
1- Install an exploded WAR directory somewhere outside Tomcat's appBase, let's assume it is in /usr/local/MyApp. [You can use a WAR file for this step instead of WAR directory, if your application runs from an unexploded war.]
2- Copy the context configuration file into [tomcat.conf]/[engine]/[hostname] directory, let's call it MyApp.xml. This file will point to the location of the application:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Context configuration file for my web application -->
<Context docBase="/usr/local/MyApp" privileged="true" antiResourceLocking="false" antiJARLocking="false">
<Resource name="jdbc/myapp-ds" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000" username="XXX" password="XXX"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" />
</Context>
3- You are now free to go and modify the configuration file.
4- Update the application by copying new version of your application in /usr/local/MyApp
Notes:
a) This solution applies to an unexpanded .war file as well, but since we use Spring's Log4JConfigListener it wouldn't run from an unexploded .war file. Tomcat doesn't explode .war files put outside appBase (webapps) folder.
b) This approach doesn't prevent you from having context.xml in /usr/local/MyApp/META-INF/context.xml since it will not be used by Tomcat in this configuration. You can use it in your dev environment, where you dump your .war file into the appBase (webapps) folder.
This is what I've got so far, still looking out for better solutions.
This is how we can manage to externalize webapp context from .WAR File
Place your .WAR file somewhere outside tomcat
Create a $APP_NAME.xml file into $TOMCAT_HOME/conf/[Engine]/[Host]/ directory.
Now file "$APP_NAME.xml" we just created need to have context definition and parameters + Any EnvironmentVariable you want specific to that context.
For e.g. I have an webapp called VirtualWebApp.
I will create file like VirtualWebApp.xml with below context definition :
<Context docBase="/home/appBase/VirtualWebApp" path="/VirtualWebApp" reloadable="true">
<Environment name="webservice.host" type="java.lang.String" value="1.2.3.4" />
<Environment name="webservice.port" type="java.lang.String" value="4040" />
</Context>
To access these environment variables you have to write below code(Just lookup) :
InitialContext initialContext = new javax.naming.InitialContext();
host = (String)initialContext.lookup("java:comp/env/webservice.host");
port = (String)initialContext.lookup("java:comp/env/webservice.port");
By referring to Apache Tomcat 5.5 Documentation:
In the $CATALINA_HOME/conf/context.xml file: the Context element
information will be loaded by all webapps
You could easily try this approach, it might work, but I'm not sure if this is a good solution especially if you are running multiple webapps on Tomcat.
I don't know how to modify Tomcat's behaviour but I could think of 2 different solutions:
different (parameterized) build scripts for each environment, so that you define a parameter called env to your build scripts and depending on the value it places the environment specific context.xml in your WAR during build.
Create an install script for each environment that first redeploys the WAR file (places it in webapps directory) and then makes modifications to the Tomcat installation depending on environment, e.g. different hostname for JDBC DataSource in context.xml.
I make heavy use of the latter approach as it works in enterprise environments. Separation of duties policies often prohibit the dev team from knowing e.g. production database passwords. Option #2 solves this problem because only IT operations have access to the environment specific install scripts after they have been created.
#n0rm1e: not sure if tomcat provides any sort of solution for you problem. But one possible solution can be:-
create an ant script with following steps:
i) Check existence of .xml file in [engine-name]/[server-name] directory. If it exists, take a back up of this/rename it.
ii) copy your war file to tomcat webapps. Restart tomcat server.
iii) copy backup-ed configuration file back to [engine-name]/[server-name] directory