I have a GWT RPC application deployed to Tomcat 8, and I want the server code to load some configuration data (hostname and port to another service). Otherwise the service works fine. I have read multiple suggestions but I cant get it to work.
A snippet from my Tomcat context.xml (I'm aware that context.xml requires me to restart tomcat when changed - that is OK).
<Context reloadable="true">
<Parameter name="config_hostname" value="192.168.2.199" override="false"/>
<Parameter name="config_port" value="8888" override="false"/>
In my service implementation I have a setup() method. In that I try to access the config by:
String hostname = getServletConfig().getInitParameter("config_hostname");
String port = getServletConfig().getInitParameter("config_port");
however that doesnt work. Can anyone put me on the right track?
----------------------- update -------------------
I have tried putting the info in web.xml like this
<web-app>
<context-param>
<param-name>hostname</param-name>
<param-value>192.168.2.199</param-value>
</context-param>
</web-app>
and using it like this (both works!) :
String h1=getServletConfig().getServletContext().getInitParameter("hostname");
String h2=getServletContext().getInitParameter("hostname");
however I don't want to put it in web.xml since I want to have a different setting for each deployment. Tomcat have conf/server.xml och conf/context.xml and I have tried those but I get NULL in the above calls then.
Which is the best way of storing server-side configurations? Please be detailed in your answer.
I have read doumentation at http://tomcat.apache.org/tomcat-8.0-doc/jndi-resources-howto.html but I obviously don't understand it.
I found the answer here in the tomcat docs at /docs/config/context.html
The syntax in context.xml should be (I was correct from the beginnig here):
<Context>
<Parameter name="hostname" value="<some-ip-address>" override="false"/>
</Context>
and the call to read it should be:
getServletConfig().getServletContext().getInitParameter("hostname");
OR
getServletContext().getInitParameter("hostname");
I'm sure I have a lot more to learn (for example to have separat params for separate web applications in Tomcat, but this is good for now).
Related
I have recently assumed duties over a site using Tomcat 8 and I am having a hard time getting a view of my manager app and site on the development server. I have set up PuTTy for ssh onto the server and I have configured port forwarding so that the base manager menu for Tomcat shows on localhost:8080 on my machine, indicating that the ssh/port forwarding appears to be working. I get the 403 error when I try to access any other element of the manager gui. I have reviewed multiple versions of this question from the past and I still think my issue is unique to them.
(links here to those answers:
403 Access Denied on Tomcat 8 Manager App without prompting for user/password
Can't access Tomcat 8 Manager App
Tomcat 8.5 - 403 Access Denied)
When looking at the previous questions they reference changing a context.xml file to comment out a valve tag inside the context tag, but my context.xml file doesn't contain this valve tag:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="" reloadable="false">
<ResourceLink global="jdbc/MyDS" name="jdbc/MyDS" type="javax.sql.DataSource" />
<ResourceLink global="jdbc/MyDS" name="jdbc/EPATestDS" type="javax.sql.DataSource" />
<Parameter name="fileStore" value="/data/xxxx" override="false"/>
<Parameter name="logStore" value="/data/xxx" override="false"/>
<Parameter name="formSite" value="x" override="false"/>
<Parameter name="answerKeyStore" value="/data/xxxxx/EPA/key" override="false"/>
<Parameter name="debugMode" value="true" override="false"/>
<Parameter name="hostname" value="https://pre-xxxxxx.com" override="false"/>
<Parameter name="ssoHostname" value="https://pre-xxx.com" override="false"/>
<Parameter name="ssoRealm" value="xxx" override="false"/>
<Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
</Context>
<!--
These 2 parameters are expected to exist but are set for all applications on the tomcat server
<Parameter name="mailServer" value="xxxxxxx" override="false"/>
<Parameter name="xxxx" value="xxx" override="false"/>
-->
(all xxx's above are to remove identifying information)
and it seems illogical to add a line to be commented. However this context file isn't located where it seems to be indicated for most other questions I've seen on this topic. My file is located at /CATALINA_HOME/webapps/ROOT##104/META-INF/context.xml whereas the solutions say to change it in /CATALINA_HOME/webapps/manager/META-INF/context.xml. When I ls --file-type on webapps it gives the manager filetype as a symbolic link to /usr/local/tomcat/webapps/manager which does not exist inside my /usr directory.
I believe the issue may be due to the way the site was configured/setup using docker, but I can't figure out the solution. The only places where /usr/local/tomcat/webapps/manager/META-INF/context.xml are located are inside of ./var/lib/docker/ directories, and there are several warnings related to not changing these files as they are managed by docker. I am unsure of where to go at this point, but I do have Dockerfiles located I just don't know which/what is needed for context here. I am unsure if I need to build new images, etc. But I can say that restarting tomcat by issuing a docker exec to the container and restarting the container itself didn't cause any changes.
edit based on comment - You have the same var/lib/docker path problems if you search for manager.xml as suggested below
You can see a similar issue when looking to make changes to tomcat-users.xml. This file only appears in directories under ./var/lib/docker/ or one other location, ./home/<username>/repo/tomcat/mec/files/tomcat-users.xml. The file at this location does have a properly configured manager-gui role, but I am unsure if this is being communicated to the proper location.
Not being a seasoned veteran with docker I have limited scope on what the consequences would be of trying to make changes to images and build new containers, etc.
Overall I am just trying to get a view of my Java EE site currently on that development server and I may even be approaching this in the wrong manner. Any and all direction would be greatly appreciated; I am unfortunately taking this up after about 2 years of predecessor leaving and not maintaining.
I have been looking at solutions for sharing session data between mutliple war files. I came across the following solution http://www.fwd.at/tomcat/sharing-session-data-howto.html
The basic idea of it is that if you have more than one war file, you can set a cookie using the sessionid of the first context that is used.
The cookie can be set using a path that will apply to all contexts/applications.
For example, if I have the following configuration for 3 applications
/myapp/app1
/myapp/app2
/myapp/app3
I can set a cookie as follows
/myapp sessionid.
The sessionid cookie will then be sent to any request with /myapp in the address. This allows the session id to then be used by any of the contexts.
The only problem with this approach is that it was written in 2003 and tested on Tomcat 4.
What are your opinions of this approach? Is there a better way of doing it?
Thanks
That article is indeed heavily outdated.
On Tomcat 5.5 and 6.0 you can just set emptySessionPath attribute to true in the <Connector> element in /conf/server.xml.
<Connector ... emptySessionPath="true">
On Tomcat 7.0 this has changed because this is now configureable from the Servlet 3.0 API on. It's then on Tomcat's side configureable by setting sessionCookiePath to / in <Context> element in any responsible context.xml file.
<Context ... sessionCookiePath="/">
As said, there's a new Servlet 3.0 API which allows you to configure the session cookie through the standard API. You can do it either declaratively by adding the following to the web.xml:
<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>
or programmatically by SessionCookieConfig which is available by ServletContext#getSessionCookieConfig().
getServletContext().getSessionCookieConfig().setPath("/");
You could do this in ServletContextListener#contextInitialized() or HttpServlet#init().
See also:
Tomcat 5.5 HTTP connector documentation
Tomcat 6.0 HTTP connector documentation - mentions potential security hole
Tomcat 7.0 context documentation
To my knowledge there is no direct way to do this, you can however use a domain level cookie if these contexts share the same domain.
You can either put the data in the cookie (I don't recommend that).
Or put a secured session Id that you can use to access some form of storage (DB or distributed cache etc) to retrieve the data you need.
If the amount of data is not astronomical and the data itself isn't changing too rapidly, you might want to consider using JNDI. This solution was designed exactly for what you are looking for.
You can have a look at official documentation or this post to tomcat-user mailing list for references & examples.
For Tomcat 8 I use the following configuration to share a session across 2 webapps:
conf/context.xml
<Context sessionCookiePath="/">
<Valve className="org.apache.catalina.valves.PersistentValve"/>
<Manager className="org.apache.catalina.session.PersistentManager">
<Store className="org.apache.catalina.session.FileStore" directory="${catalina.base}/temp/sessions"/>
</Manager>
...
</Context>
I deploy the same simple webapp twice log.war and log2.war:
/log
/log2
I can now log-in to /log and have the user displayed in /log2, this does not work with the tomcat default configuration.
The session value is set and read:
HttpSession session=request.getSession();
session.setAttribute("name",name);
HttpSession session=request.getSession(false);
String name=(String)session.getAttribute("name");
I used this project as example: https://www.javatpoint.com/servlet-http-session-login-and-logout-example
Most examples/solutions use a in-memory database which requires more setup work:
redis
hazelcast
My code is working on tomcat 8 version 8.0.33 but on 8.5.4 i get :
An invalid domain [.mydomain] was specified for this cookie.
I have found that Rfc6265CookieProcessor is introduced in tomcat 8 latest versions.
It says on official doc that this can be reverted to LegacyCookieProcessor in context.xml but i don't know how.
Please let me know how to do this.
Thanks
You can try in context.xml
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />
reference:
https://tomcat.apache.org/tomcat-8.0-doc/config/cookie-processor.html
Case 1: You are using Standalone Tomcat & have access to change files in tomcat server
Please follow answer by #linzkl
Case 2: You are using Standalone Tomcat but you don't have access to change files in tomcat server
Create a new file called context.xml under src/main/webapp/META-INF folder in your application & paste the content given below
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" />
</Context>
When you deploy your application in Standalone Tomcat, the context.xml file you placed under META-INF folder will override the context.xml file given in tomcat/conf/context.xml
Note: If you are following this solution, you have to do it for every single application because META-INF/context.xml is application specific
Case 3: You are using Embedded Tomcat
Create a new bean for WebServerFactoryCustomizer
#Bean
WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return new WebServerFactoryCustomizer<TomcatServletWebServerFactory>() {
#Override
void customize(TomcatServletWebServerFactory tomcatServletWebServerFactory) {
tomcatServletWebServerFactory.addContextCustomizers(new TomcatContextCustomizer() {
#Override
public void customize(Context context) {
context.setCookieProcessor(new LegacyCookieProcessor());
}
});
}
};
}
Enabling the LegacyCookieProcessor which is used in previous versions of Tomcat has solved the problem in my application. As linzkl mentioned this is explained in Apache's website https://tomcat.apache.org/tomcat-8.0-doc/config/cookie-processor.html.
The reason is that the new version of Tomcat does not understand the . (dot) in front of the domain name of the Cookie being used.
Also, make sure to check this post when you are using Internet Explorer. Apparently, it's very likely to break.
You can find context.xml in the following path.
tomcat8/conf/context.xml
<?xml version="1.0" encoding="UTF-8”?>
<!-- The contents of this file will be loaded for each web application —>
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!-- <Manager pathname="" /> -->
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor"/>
</Context>
The problem is still with Tomcat9. Same process need to follow for Tomcat 9 to set the class.
Add the class in context.xml file.
If you are using eclipse to run the application, need to set in the context.xml file in the server folder. Refer the below screenshot for more reference.
Hope this helps someone.
SameSite issue in tomcat version < 8.5.47 has resolved
In Tomcat 8.5.47 and bellow (Tomcat 8 versions), setting CookieProcessor tag to enable same site (as given bellow) in context.xml does not work due to a bug in Tomcat.
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" sameSiteCookies="none" />
If you find in this situation where it is not a easy thing to upgrade tomcat immediately (which I faced recently), or if you find any other case where you just need custom processing in cookies; You can write your own CookieProcessor class to get around.
Please find a custom CookieProcessor implementation and details of it's deployment steps here.
In my case I wrote a custom CookieProcessor based on LegacyCookieProcessor source code that allows tomcat 8.5.47 to enable SameSite attribute in cookies.
As mentioned by #atul, this issue persists in Tomcat 9. It will most likely persist moving forward with all future versions of Tomcat, since this is the new standard.
Using the legacy cookie processor (by adding the line above to the context.xml file) is working well for us. However, the true 'fix' is to adjust how your cookie is formed in the first place. This will need to be done in your application, not in Tomcat.
The new cookie processor does not allow the domain to start with a . (dot). Adjusting your cookie (if possible) to start with a value other than that will fix this problem without reverting to the old, legacy cookie processor.
Also, it should be obvious, but I didn't see it mentioned above: after updating the context.xml file, you need to restart the Tomcat service for the change to take effect.
Cheers!
I would like to disable page "People" in Hudson. I don't want users to see other users. Is it possible to do?
I don't know if you can do it directly with Hudson, but you certainly be able to do it if you run Hudson within a Tomcat instance (I run mine in a Tomcat 7 without any problem).
You would define a JSP security-constraint, a bit like those ones (note: adapted for LDAP because I defer all user authentication to the webapp container of Hudson: in my case, Tomcat)
The OP asks:
You're suggesting to make changes to hudson/WEB-INF/web.xml? Could you please explicitly mention the file I have to change?
#Vincenzo: I don't! I never touch one bit of the hudson.jar. I only use it within a Tomcat instance, meaning:
I declare in <tomcat>/conf/Catalina/localhost a context for each Hudson I want to manage:
hudson-xxx -> /home/me/context/hudson-xxx.xml
(it is a link because I want to upgrade Tomcat easily, so I externalize the context definition outside of Tomcat). I define my Realm for ACL purposes:
<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/home/me/hudson/hudson.war" path="/hudson-xxx">
<Realm className="org.apache.catalina.real.CombinedRealm" >
<Realm className="org.apache.catalina.real.JNDIRealm" debug="99"
connectionURL="ldap://xxxxx:389"
alternateURL="ldap://xxxxx:389"
connexionName="yyyy"
connectionPassword="zzzz"
userPattern="CN={0},OU=...,DC=..."
userRoleName="memberOf"
useSubtree="false"
roleBase="OU=...,DC=..."
roleName="cn"
roleSearch="(member={0})"
roleSubtree="false"
/>
</Realm>
<Environment name="HUDSON_XXX" value="/home/me/hudson/hudson-xxx-home" type="java.lang.String" override="false" />
</Context>
(With that context, a hudson.war stored outside of Tomcat is automatically deployed with the </tomcat>/webapps directory, and access from http://tomcat-server/hudson-xxx, with an LDAP-based authentication)
I suggests modifying the </tomcat>/conf/web.xml to add security-constraint which would prevent anybody to access the user page while letting only certain tomcat users (as defined in /conf/tomcat-users.xml.
(I haven't tested it yet)
I am trying to set a system property in tomcat config file so it can be read by System.getProperty() code. This is probably a simple task but I am not able to figure this out. Here is want I tried with no success.
Modified context.xml in tomcat settings.
<Context>
....
<Parameter name="run.mode" value="test"/>
<Environment name="run.mode" value="test" type="java.lang.String"/>
</Context>
I don't want to modify container settings, just the server settings.
PS. I am fairly new to to the container and JVM webapp world. Still making sence of things. Right now I am working with Lift.
Use the JAVA_OPTS environment variable when launching Tomcat, like this:
JAVA_OPTS='-Drun.mode=test' start.sh