Tomcat custom context.xml file is never taken into account - java

I have currently a problem with the Tomcat configuration of a web application (I use Tomcat 8.5.57).
This web application is packaged in a war file containing, among others, html files and css files.
This application works well.
Now, I have a request from a customer asking to be able to modify the look and feel of the application from outside of the war via a custom css file managed by the client (used to set the logo of the client or stuff like that).
So I tried to create a custom context file, called custom.xml, that I placed in tomcat\conf\Catalina\localhost directory.
This file looks like :
<Context docBase="E:/somedirectory/support"
path="/app/css"
reloadable = "false"
unpackWAR = "false"
swallowOutput = "true" >
<WatchedResource>custom.css</WatchedResource>
</Context>
I put the custom.css file containing some css instructions as test in the E:/somedirectory/support directory.
In the html file of my web application, I have the following line in the head section :
<link rel="stylesheet" href="css/custom.css" media="screen" type="text/css"/>
The problem is that my custom.css file is never taken into account.
When I open the Sources tab of Chrome's developer tools, I see a custom.css file in the hierarchy in app/css as expected (probably due to the line in the html file), but it is hopelessly empty.
I tried a lot of things found on the Web and on stackoverflow, but nothing worked for me...
Can someone help me ?
Thank you !

The path attribute of <Context> element is ignored outside of server.xml:
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. [from Tomcat documentation]
Therefore you have two choices:
You can define a new context (new web application) with context path /app/css by creating a file named conf\Catalina\localhost\app#css.xml and content:
<Context docBase="E:\somedirectory\support" />
This way everything under the /app/css subtree will only be served from the E:\somedirectory\support directory.
You can redefine your application context to include an additional virtual directory (beside the contents of the WAR file) by adding a file named conf\Catalina\localhost\app.xml with content:
<Context>
<Resources>
<PreResources className="org.apache.catalina.webresources.DirResourceSet"
base="E:\somedirectory\support"
webAppMount="/css" />
</Resources>
</Context>
This way, while serving a request for /app/css/foo/bar, Tomcat will first look for foo/bar in E:\somedirectory\support and then in the WAR file.

Related

Tomcat context docbase not working to serve static images

I need to serve images directly from a folder outside war file using tomcat server.
I tried few options like setting the image location path in context docbase but its not working.
I configured that in server.xml of tomcat as follows
<Context docBase="E:\images\" path="/images" />
I need a solution directly from tomcat side and cant make any code changes to serve them.
Already gone through these links but of no use:
How to config Tomcat to serve images from an external folder outside webapps?
Tomcat version : 8.5, my images are in .svg format.
Please help me in this.
This may help #Kirti or someone who is facing this problem.
I tried with following solution in same case in my project:-
I created a directory on server as E:\MyProject\Images
Added following <Context /> tag in server.xml inside <Host></Host> tag
<Context docBase="E:\\MyProject\\Images" path="/images"/>
Then I could simply access the images using following link:
http://localhost:8080/images/firstImage.jpg
Note: For windows we separate path with \\ and in linux need to use //
You are missing the Closing slash of the context tag. Also forward slashes are preferable and work as well on Windows.
<Context docBase="E:/images/" path="/images" />

Provide <Realm/> info to Tomcat on eclipse

Our web application has an appName.xml file in our Tomcat directory structure at <tomcatInstall>/conf/Catalina/localhost/. Its entire text is:
<?xml version="1.0" encoding="UTF-8"?>
<Context crossContext="true">
<Realm className="com.blah.ApDataSourceRealm"
dataSourceName="jdbc/blahDev"
roleNameCol="blahRole"
userCredCol="blahToken"
userNameCol="blahCol"
userRoleTable="blahTable"
userTable="blahTable"
/>
</Context>
I made sure to delete the tomcat 8 install in eclipse and then add it back again; I understand that is what copies all the tomcat installation stuff to the workspace locations. When I attempt to run the server on eclipse, the login page is displayed, but the username/password is always rejected.
I fixed it once by finding the eclipse copy of server.xml in the eclipse-workspace folder tree (...eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/temp1/conf). But the next time I rebooted the computer and ran it again, the login failed, and on checking server.xml, I find that it was overwritten this morning. I assume eclipse overwrites it under some conditions, perhaps on eclipse startup? I put the <Realm ... /> tag into server.xml within <Context ... /> again, and it is working again.
Where should this information go? I'd like to put it somewhere that it won't disappear from eclipse. I don't think we want this realm tag in the actual server.xml (as opposed to the one local to eclipse), because this one is specific to the development environment. So where can it be put on my machine so that it is used by eclipse's Tomcat and yet doesn't interfere with the application's overall source?
One of the way is to put your <Context> configuration in the webapp/META-INF/context.xml.
Reference :
Individual Context elements may be explicitly defined:
In an individual file at /META-INF/context.xml inside the application
files. Optionally (based on the Host's copyXML attribute) this may be
copied to $CATALINA_BASE/conf/[enginename]/[hostname]/ and renamed to
application's base file name plus a ".xml" extension.
In individual
files (with a ".xml" extension) in the
$CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The context
path and version will be derived from the base name of the file (the
file name less the .xml extension). This file will always take
precedence over any context.xml file packaged in the web application's
META-INF directory.
Inside a Host element in the main conf/server.xml.
Default Context elements may be defined that apply to multiple web
applications. Configuration for an individual web application will
override anything configured in one of these defaults
Where should this information go? I'd like to put it somewhere that it
won't disappear from eclipse
So where can it be put on my machine so
that it is used by eclipse's Tomcat and yet doesn't interfere with the
application's overall source?
When you create a Tomcat in Eclipse , a server project will also be created. This project stores the configuration for the created tomcat instance which will be copied to Tomcat instance 's conf folder (i.e. eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/temp1/conf when tomcat starts.
So , if you do not want to add the Realm configuration to your project source codes likes /webapp/META-INF/context.xml , you can add it to the context.xml in the server project.

How to add a favicon to a Google appengine app

I am trying to add a favicont to a appengine web app but not completely sure how to go about it.
What i've done:
I added the following to the of my appengine-web.xml file
tag: The favicon is located in src/main/webapp...
It still doesn't get served. Any idea what i;m doing wrong? I also added /
Put your favicon image inside the war directory of project . It works for me . Nothing else needed . Path should be like this /YourProjectName/war/favicon.ico. You can verify this path by right clicking on properties for your favicon image .
The syntax that you used is the one for the app.yaml file (which is used by the environments other than Java)
For the Java environment the static files are specified in the appengine-web.xml file. Look for the <public-root> and the <static-files> tags in the appengine-web.xml Reference:
< public-root >
Optional. The is a directory in your application that
contains the static files for your application. When a request for a
static file is made, the for your application is
prepended to the request path. This gives the path of an application
file containing the content that is being requested.
The default is /.
For example, the following would map the URL path /index.html to the
application file path /static/index.html:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<!-- ... -->
<public-root>/static</public-root>
<!-- ... -->
</appengine-web-app>
and
< static-files >
Optional. The element specifies patterns that match
file paths to include and exclude from the list of static files,
overriding or amending the default behavior. Static file are served
from dedicated servers and caches that are separate from the
application servers and are useful for serving static content such as
images, CSS stylesheets or JavaScript files.

How to provide a context configuration for a web application in Tomcat?

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

favicon.ico in Java WAR file

Can anybody provide some instruction on how to setup a war file to show a favicon.ico in the browser address bar?
You can also use the following HTML markup in your HTML:
<link rel="icon" type="image/gif" href="/img/image.gif">
Most newer browsers should support it and I think it's generally a more clean way since you can use any image type/name/location you want.
This might be different in different application servers. For tomcat, the favicon comes from the directory your root context is mapped to. So if your application is mapped to the root context [/], just place the favicon.ico file in the top level folder in your war file.

Categories