I have one master and two slave into domain modes, using and httpsession and distributable into web.xml but the session is not shaing into domains, Im access one node and work, but when access the other node the session is not sharing.
the configuration is the following
1 master
2 slaves(slave1, slave2)
1 server group (demo)
2 nodes (node11 server slave1, node21 server slave2 )
When access node 11 and make the login, and then chage to node21 the session is not persisted, and the result is null.
and try with another app for session but have the same issue
jboss eap is 7.2 and jdk is open jdk 1.8
I try using two different application of session sharing, and none of work.
Im try the same on on server on different ports and the session was shared
You need to add <distributable/> tag in your web.xml. You may need to enable session replication on your JBoss domain server as well. Refer https://developer.jboss.org/thread/277766 for more details.
You should also read JBoss EAP documentation on this Configuring high availbility
I'm not sure what you mean by master vs slave modes. This is not a concept on which EAP clustering relies.
Additionally, domain mode is about management, not about clustering. These are completely orthogonal concepts.
From a management perspective, servers within a given server-group share the same configuration. Generally, if the server-group is configured to use an "ha" profile (which defines a JGroups subsystem which is the starting point for cluster configuration), and multicast is allowed on your network, servers should form a cluster out-of-the-box.
If this is not happening, look to your server logs to figure out what is happening, and to the docs for configuring JGroups discovery w/out multicast.
Related
We want to split a working application in two different .war files in order to be able to update one app without affecting the other. Each webapp will have different a UI, different users and different deploy schedule.
The easiest path seems to be sharing the same session, so if app A set session.setAttribute("foo", "bar") app B will be able to see it.
Is there a way to share the HttpSession state for both apps in the same Tomcat instance?
Our app is running on a dedicated Tomcat 5.5, there are no other apps running on the same tomcat instance, so any security concerns regarding the session sharing are not a problem. We're running multiple Tomcat instances, but the balancer is using sticky sessions.
If it's not possible or this session sharing is a really bad idea please leave a comment.
You should not share HttpSession; but you can share other objects. For example, you can register an object via JNDI and access the same object in all your apps (databases use this to pool connections).
One thing to be aware of is that two web apps will use different classloaders. If you want to share objects, they need to use the same version of the class from the same classloader (or else you will get LinkageErrors). That means either putting them in a classloader shared by both web apps (system classpath for example) OR using serialization to effectively drain and reconstitute the object in the right classloader with the correct version of the class.
If you want to use Spring, there's a project called Spring Session:
https://github.com/spring-projects/spring-session
Quoting: "HttpSession - allows replacing the HttpSession in an application container (i.e. Tomcat) neutral way"
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
If the two webapps are so closely coupled that they need to share objects, why are you splitting it in two? Even if you manage them somewhat independently any decent build management system should be able to create a single WAR file for deployment.
A solution like Aaron suggest with JNDI will work, but only if both webapps are running on the same server. If the units are tightly coupled and you are going to be running it on the same server anyway ... might as well have a single WAR.
If you really do want them to stand independently I'd seriously examine the data exchange between the two. Ideally you'd want them to only share relevant data with one another. This data could be passed back and forth via POST (or GET if more appropriate) parameters, you might even consider using cookies.
One way of doing this is described in this blog post: Session sharing in Apache Tomcat
Summary: Add emptySessionPath to the Connector configuration and crossContext to the Context
redison download
conf/context.xml
<Context sessionCookiePath="/">
...
<Manager className="org.redisson.tomcat.RedissonSessionManager"
configPath="${catalina.base}/conf/redisson.yaml"
readMode="REDIS" />
</Context>
conf/redisson.yaml
singleServerConfig:
address: "redis://<host>:6379"
sessionCookiePath="/" makes Tomcat use the same session id for different web apps.
RedissonSessionManager makes session to be persisted in 'shared space'
I was not able to achieve desired result with org.apache.catalina.session.FileStore PersistentManager in shared context.xml, I faced issues with session deserialization in background expiration monitor thread. It failed to deseriazile the session because it was using common classloader without webapp serializable models in classpath. Theoretically PersistentManager could be configured for each web app separately (to have proper classpath) in WEB-INF/context.xml but I failed to make it work.
org.apache.catalina.session.JDBCStore PersistentManage was promising because it expose last_access column for the session so it is not required to deserialize session_data, but it was saving app_name all the time causing same session id to be written as different rows for diffrent web apps. Thus session data was not stored in the shared place.
Spring Session has it`s own way to create session id. I was not able to find solution to force Spring Session to create same session id for different web apps.
Solution with core tomcat session id generation (with ability to generate the same for different web apps and RedissonSessionManager, which store data using session id as the only key and has it's own expiration mechanism) finally worked for me. The solution works perfectly with #SessionScope spring beans.
You can do by taking servlet context by your context root.
For retrieving variable.
request.getSession().getServletContext().getContext("/{applicationContextRoot}").getAttribute(variableName)
For setting variable:
request.getSession().getServletContext().getContext("/{applicationContextRoot}").setAttribute(variableName,variableValue)
Note: Both the applications should deployed in the same server.
Pls let me know if you find any problem
Tomcat 8 :
i had to do : <Context crossContext="true" sessionCookiePath="/"> in conf/context.xml
more details on config attributes here
and then to set the value(like #Qazi's answer):
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.setAttribute(variableName,variableValue)
to get the value:
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.getAttribute("user");
I developed session state server for tomcat using python.
Due to this I don't need to change the code already written for creating/accessing and destroying session. Also as there is separate server/service which is handling and storing session so not master cluster is needed. There is no session replication (as in tomcat clustering) in this case, rather this is session sharing between web farming.
You should not split your app that way in order by have high availability. You could deploy the whole app on many tomcat instances.
I have a web application that get deployed on a jboss (eap 6.2) domain with 2 nodes.
There are certain startup processes that need to be excecuted, however right now the processes run on both nodes. This is undesirable, I need the process to run only on 1 server (identified as primary).
Obviously this can be done by having a special system property set up 1 of the servers, howeever I am wondering if there is a standard Java EE way of designating a node as primary and then reading that configuration in the code?
There is no defined standard. Some application servers provide HA Singletons (https://developer.jboss.org/wiki/JBMHASingleton for JBoss 4.x and http://www.jboss.org/quickstarts/eap/cluster-ha-singleton/ for JBoss 7/Wildfly 8).
There are some approaches like using JGroups or persisting the state in some sort of database. You could also use a clustered JMS Topic. The first node broadcasts "I'm initializing" and others have to listen to it. That's not the best approach but it's within Java EE bounds.
I am building a cluster environment with weblogic 12c as application server and I am using weblogic as LOADBALANCER,
my problem that every time I send the request to the load balancer it sends it to a different node although it should send it to the same node !!
I am sure there is a missing property to enable affility (stickiness).
any suggestions guys !
I am assuming you are using " WebLogic Proxy Plug-In " - can you confirm this is true.
The default loadbalancing algorithm is round robin When using weblogic proxy plug-in hence the behaviour you are observing is expected.
Session Stickiness comes into play only when you have an application which is using sessions, and you have defined WLCookieName parameter to the correct cookie name value in the plug-in.
http://docs.oracle.com/cd/E21764_01/web.1111/e14395/plugin_params.htm#CIHFFGEB
Tell us what request are you sending to the loadbalancer ?
is it to a static resource (like index.htm)
or is it to an application where you are maintaining a session.
Share some bit of the plugin configuration you have done.
My goal is to have 2 different tomcat servers that run the same web-application and be using the same DB,
I'm using spring + JPA with MySQL DB.
Is this a straight forward practice? can i just deploy and start-up both tomcats?
OR - is there any preliminary configuring to do? (i.e Do i have to configure JPA in both apps to be synchronized with each other? etc..)
EDIT - we are going to use HA-Proxy as a load balancer.
regards,
The simplest way is to configure your load balancer to point one user always to the same Tomcat instance. Otherwise, if your load balancer will point randomly for each request, you will have problems with sessions. By default one Tomcat won't be able to share session with another. In the other hand, you can configure your Tomcats to replicate sessions between nodes or use common session store. There are at least few ways to do that.
We want to split a working application in two different .war files in order to be able to update one app without affecting the other. Each webapp will have different a UI, different users and different deploy schedule.
The easiest path seems to be sharing the same session, so if app A set session.setAttribute("foo", "bar") app B will be able to see it.
Is there a way to share the HttpSession state for both apps in the same Tomcat instance?
Our app is running on a dedicated Tomcat 5.5, there are no other apps running on the same tomcat instance, so any security concerns regarding the session sharing are not a problem. We're running multiple Tomcat instances, but the balancer is using sticky sessions.
If it's not possible or this session sharing is a really bad idea please leave a comment.
You should not share HttpSession; but you can share other objects. For example, you can register an object via JNDI and access the same object in all your apps (databases use this to pool connections).
One thing to be aware of is that two web apps will use different classloaders. If you want to share objects, they need to use the same version of the class from the same classloader (or else you will get LinkageErrors). That means either putting them in a classloader shared by both web apps (system classpath for example) OR using serialization to effectively drain and reconstitute the object in the right classloader with the correct version of the class.
If you want to use Spring, there's a project called Spring Session:
https://github.com/spring-projects/spring-session
Quoting: "HttpSession - allows replacing the HttpSession in an application container (i.e. Tomcat) neutral way"
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
If the two webapps are so closely coupled that they need to share objects, why are you splitting it in two? Even if you manage them somewhat independently any decent build management system should be able to create a single WAR file for deployment.
A solution like Aaron suggest with JNDI will work, but only if both webapps are running on the same server. If the units are tightly coupled and you are going to be running it on the same server anyway ... might as well have a single WAR.
If you really do want them to stand independently I'd seriously examine the data exchange between the two. Ideally you'd want them to only share relevant data with one another. This data could be passed back and forth via POST (or GET if more appropriate) parameters, you might even consider using cookies.
One way of doing this is described in this blog post: Session sharing in Apache Tomcat
Summary: Add emptySessionPath to the Connector configuration and crossContext to the Context
redison download
conf/context.xml
<Context sessionCookiePath="/">
...
<Manager className="org.redisson.tomcat.RedissonSessionManager"
configPath="${catalina.base}/conf/redisson.yaml"
readMode="REDIS" />
</Context>
conf/redisson.yaml
singleServerConfig:
address: "redis://<host>:6379"
sessionCookiePath="/" makes Tomcat use the same session id for different web apps.
RedissonSessionManager makes session to be persisted in 'shared space'
I was not able to achieve desired result with org.apache.catalina.session.FileStore PersistentManager in shared context.xml, I faced issues with session deserialization in background expiration monitor thread. It failed to deseriazile the session because it was using common classloader without webapp serializable models in classpath. Theoretically PersistentManager could be configured for each web app separately (to have proper classpath) in WEB-INF/context.xml but I failed to make it work.
org.apache.catalina.session.JDBCStore PersistentManage was promising because it expose last_access column for the session so it is not required to deserialize session_data, but it was saving app_name all the time causing same session id to be written as different rows for diffrent web apps. Thus session data was not stored in the shared place.
Spring Session has it`s own way to create session id. I was not able to find solution to force Spring Session to create same session id for different web apps.
Solution with core tomcat session id generation (with ability to generate the same for different web apps and RedissonSessionManager, which store data using session id as the only key and has it's own expiration mechanism) finally worked for me. The solution works perfectly with #SessionScope spring beans.
You can do by taking servlet context by your context root.
For retrieving variable.
request.getSession().getServletContext().getContext("/{applicationContextRoot}").getAttribute(variableName)
For setting variable:
request.getSession().getServletContext().getContext("/{applicationContextRoot}").setAttribute(variableName,variableValue)
Note: Both the applications should deployed in the same server.
Pls let me know if you find any problem
Tomcat 8 :
i had to do : <Context crossContext="true" sessionCookiePath="/"> in conf/context.xml
more details on config attributes here
and then to set the value(like #Qazi's answer):
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.setAttribute(variableName,variableValue)
to get the value:
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.getAttribute("user");
I developed session state server for tomcat using python.
Due to this I don't need to change the code already written for creating/accessing and destroying session. Also as there is separate server/service which is handling and storing session so not master cluster is needed. There is no session replication (as in tomcat clustering) in this case, rather this is session sharing between web farming.
You should not split your app that way in order by have high availability. You could deploy the whole app on many tomcat instances.