I have a Tomcat 6 instance running on my local machine.
I have made the following changes in its configuration:
In /conf/context.xml
– changed the tag as follows
<Context crossContext="true">
In /conf/server.xml
– changed the tag as follows
<Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true"
connectionTimeout="20000"
redirectPort="8443" />
Suppose I have a WAR file named SampleProject.war
deployed here which extract to folder SampleProject
.
In some servlet in this WAR, say SampleServlet
, I write two blocks of code as follows :
ServletContext context1 = session.getServletContext();
and
ServletContext context2 = session.getServletContext().getContext("/SampleProject");
What is the difference between context1
and context2
? I thought that both refer to the application context. But if I set some attribute in context1
and access in context2
, I don't get the value in context2
.
Any help would be appreciated.
I feel your question was slightly misunderstood and that you already had the basic understanding of the API i.e. once a web-app sets its crossContext="true"
it could use getContext()
to get access to a context that corresponds to some other web-app deployed on the server.
getServletContext().getContext() equals NULL unless <Context crossContext="true">
From what I've understood, your question actually is that in /SameWebApp
why
ServletContext context1 = session.getServletContext();
context1.setAttribute("contextAttribute", new Object());
ServletContext context2 = session.getServletContext().getContext("/SameWebApp");
System.out.println(context1.equals(context2)); // prints false, or
System.out.println(context2.getAttribute("contextAttribute")); // prints null (at least they could have been clones)
In just one word, the answer is "Security". Imagine if you couldn't guarantee that an "adminEmail" context attribute has not been tampered with by an evil web-app having its crossContext=true
. Your app could potentially help compromise itself as soon as that "Forgot Password" request comes! :)
Tomcat 7 provides a class ApplicationContext implements ServletContext
that returns from getContext("/context-root")
as
if (context.getCrossContext()) {
// If crossContext is enabled, can always return the context
return child.getServletContext();
} else if (child == context) {
// Can still return the current context
return context.getServletContext();
} else {
// Nothing to return
return (null);
}
Here context
belongs to current web-app and child
represents the other web-app. But, hold on, what makes Tomcat call it a child?
These two actually aren't ApplicationContext
but instances of StandardContext
a class that implements Context
but instead of servlet specific things holds Tomcat specific config settings for a web-app like crossContext, hostname, mimeMappings etc. StandardContext.getParent()
gives you the Container
and hence it has been referred to as a child above.
Anyways, we're interested in the case when child == context
is true i.e. getContext()
was called on the "/SameWebApp". The call is being delegated to StandardContext.getServletContext()
which has been implemented to return a different instance of ApplicationContext
.
This is why the attributes you set in context1
are not found in context2
.
But wait, there's some more to it. Why does StandardContext.getServletContext()
return like
return (context.getFacade());
A Tomcat instance is basically executing two types of Java code:
The container code is "Trusted" and may need to run with elevated privileges sometimes. The user code, on the other hand, is not trusted and needs to be restricted from compromising Tomcat internals.
One of the things that Tomcat does to achieve this is always wrap an ApplicationContextFacade
around the ApplicationContext
(and hence the StandardContext
as well). So just to recap, what appears to be a simple ServletContext
implementation is actually a StandardContext
mapped to an ApplicationContext
which is then wrapped within an ApplicationContextFacade
.
For further information on how the ApplicationContextFacade
works using Reflection in tandem with Globals.IS_SECURITY_ENABLED
and SecurityUtil.isPackageProtectionEnabled()
settings please take a look at Why do Servlets access Tomcat ApplicationContext through a Facade on SO.
References:
Tomcat 7 Source Code (Download Link)
Absolutely those two context objects are different from another.. Context1 object gives current web application servlet context obj. ( ServletContext context1 = session.getServletContext();)
and
context2 object gives the servletcontext obj of specified web application (ServletContext context2 = session.getServletContext().getContext("/SampleProject");)
you are setting object in one context and trying to retrieve using another context, so it is not possible to get attribute from another web application context by putting it in current application context. But you can get attribute resides in another web application context by using second method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With