Overriding the default session manager with embedded tomcat 7 java - session

I am trying to override the tomcat session manager with an embedded tomcat.
These are the steps preformed in-order to load the context.xml that defines the manager entity.
..
Context context = tomcat.addWebapp(contextPath, appBase);
File configFile = new File ("D:\\context.xml");
context.setConfigFile(configFile.toURI().toURL());
tomcat.start();
..
The session manager seems to be recognized as it's constructor is being invoked but the startInternal() method is never invoked and the session manager being used is the old tomcat session manager.
The weird thing is that when defining the same configuration in a non embedded tomcat, the session manager is being overridden without problems.
Would appriciate any help on the subject.

Non embedded tomcat uses server.xml and embedded tomcat does not uses server.xml file rather we need to pass the arguments in the method.

Related

LegacyCookieProcessor in standalone Tomcat and Spring Boot [duplicate]

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!

OpenLiberty NameNotFoundException: java:/comp/env

I have a web app running in Tomcat correctly that I want to run on the new OpenLiberty server, the app is starting correctly inside OpenLiberty but at the moment of the database connection initiation is throwing the following exception:
[Default Executor-thread-15] 2018-03-15 15:02:30 ERROR TomcatConnectionManager:41 - Loading jdbc/mysql/myaap failure
javax.naming.NameNotFoundException: java:/comp/env
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLName.<init>(JavaURLName.java:83)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLNameParser.parse(JavaURLNameParser.java:39)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLNameParser.parse(JavaURLNameParser.java:60)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext$NameUtil.<init>(JavaURLContext.java:474)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext.lookup(JavaURLContext.java:321)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext.lookup(JavaURLContext.java:370)
at org.apache.aries.jndi.DelegateContext.lookup(DelegateContext.java:161)
The above exception is thrown during the lookup phase:
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
Is there any way to make it work on OpenLiberty doing less changes possible?
On OpenLiberty the equivalent lookup would look like this:
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
The key is that you need to use java:comp/... instead of java:/comp/...
The reason why Tomcat is different than Liberty is because Tomcat is just a servlet container and Liberty conforms to the full Java EE specification.
According to section EE.5.2.2 of the Java EE 7 spec:
The application component’s naming environment is composed of four logical
namespaces, representing naming environments with different scopes. The four
namespaces are:
java:comp – Names in this namespace are per-component (for example, per enterprise
bean). Except for components in a web module, each component gets
its own java:comp namespace, not shared with any other component. Components
in a web module do not have their own private component namespace.
See note below.
java:module – Names in this namespace are shared by all components in a
module (for example, all enterprise beans in a single EJB module, or all components
in a web module).
java:app – Names in this namespace are shared by all components in all modules
in a single application, where “single application” means a single deployment
unit, such as a single ear file, a single module deployed standalone, etc.
For example, a war file and an EJB jar file in the same ear file would both have
access to resources in the java:app namespace.
java:global – Names in this namespace are shared by all applications deployed
in an application server instance. Note that an application server instance
may represent a single server, a cluster of servers, an administrative
domain containing many servers, or even more. The scope of an application
server instance is product-dependent, but it must be possible to deploy multiple
applications to a single application server instance.
Had a similar problem going between WebSphere and Tomcat. I'm developing and testing on a Tomcat server and using utilities I can't change that handle the DB connection to our DB2. On WebSphere it uses a constant set to "jdbc/COMPDB2" to retrieve the DataSource when I configure Tomcat and my Web.xml file it resolves to "java:comp/env/jdbc/SFCCDB2"
My work around for on local work space it to add a listener to copy the resource to the level in the InitialContext. I'm not very experienced with the server side of things but this is working so far using TomEE 7.0.81.
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/SFCCDB2");
javax.naming.Context envCtx = (javax.naming.Context) ctx.lookup("java:comp/env");
try{
/*
Added this because after redeploying code to the server it would error
connecting to the DB with an SQLException Datasource is closed
*/
DataSource dataSource = (DataSource) ctx.lookup("jdbc/COMPDB2");
ctx.destroySubcontext("jdbc");
} catch (NamingException e){
//Doesn't exist; safe to just add
}
ctx.createSubcontext("jdbc");
ctx.bind("jdbc/COMPDB2", ds);
ctx.close();

UnknownSessionException when using SessionScoped CDI managed beans with Shiro managed sessions

I am developing a JSF web based application that makes use of CDI managed beans and Shiro managed sessions. The problem I've got is when a JSF page that references an object annotated with #javax.enterprise.context.SessionScoped an UnknownSessionException is thrown. I have set the logging level to finest and looking through the application server log file I can see that when the user accesses the login page a new session is created along with a cookie that sets JSESSIONID to b2b69494-2236-467f-9e0b-3c262c74b7c4. When the user accesses the page that references the SessionScoped bean the cookie is updated to have a JSESSIONID set to 49253beaee601d4107cba4b61c77, at this point an UnknownSessionException is thrown. When accessing pages that reference a managed bean annotated with either #javax.enterprise.context.ApplicationScoped or #javax.faces.view.ViewScoped everything works fine.
It appears that when accessing a page that references a session scoped bean, the servlet container is creating a new session rather than allowing the Shiro managed session to be used. If I configure Shiro to use something other than JSESSIONID then the error isn't thrown but instead two sessions appear to be created, one managed by Shiro and the other managed by the servlet container.
The contents of my shiro.ini file is
[main]
authc.loginUrl = /login.xhtml
authc.usernameParam = login:username
authc.passwordParam = login:password
authc.rememberMeParam = login:rememberMe
user.loginUrl = /login.xhtml
authc.successUrl = /app/index.xhtml
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
[users]
admin = password
[urls]
/login.xhtml = authc
/app/** = user
My environment is using Glassfish 4.1, Java EE version 7, Mojarra version 2.2.7 for JSF, Weld version 2.2.2 for CDI, and Shiro version 1.2.3. I have also reproduced the same issue on Glassfish version 4.0 albeit with earlier versions of Mojarra and Weld.
I have uploaded the relevant portion of the application server log to PasteBin which can be accessed with the URL http://pastebin.com/2sPHfdTQ
I've also created an example Maven project to demonstrate the problem. The example project can be downloaded from https://www.dropbox.com/s/1x9pe2o9ja0q9jw/TestJavaEE-web.zip?dl=0 which contains the source code and the complied war file.
Is anyone else currently using CDI managed session scoped beans with Shiro managed sessions, and if so have you had any problems?
Is there a configuration setting I've missed either in Shiro or GlassFish or is this a bug?
Note: I have previously posted this question on the Shiro mailing list but I'm yet to find a solution and I'm hoping that there will be a wider audience on StackOverflow.

Spring #Scheduled job - Get base application path

I have a Spring MVC application and in it I am running a periodic job using a class with method annotated as #Scheduled
In this method, I want to get the base application path i.e. http://localhost:8080/ or http://www.mywebsite.com/ based on whether this is my local system or production system.
How can I do this? I do not have access to HttpServletRequest because this is not a Controller class.
Any hints would be appreciated
In my opinion it is a good idea to use profiles and store properties like base application path in properties file - where each environment has its own property file: config_dev.properties, config_production.properties
Once they are there you can load them in job-like classes using Environment (described on SpringSource blog).
How to configure Tomcat and Spring to use profiles: Spring 3.1 profiles and Tomcat configuration
Put a myconfiguration.properties out of your application, to let the application know that whether its running locally or in production. And then in your method annotated as #Scheduled just read the Property file.
String configPath = System.getProperty("config.file.path");
File file = new File(configPath);
FileInputStream fileInput = new FileInputStream(file);
Properties properties = new Properties();
properties.load(fileInput);
And provide the agrument,
-Dconfig.file.path=/path/to/myconfiguration.properties
when running your application server (or container). This can be done by putting,
JAVA_OPTS="$JAVA_OPTS -Dconfig.file.path=/path/to/myconfiguration.properties"
at the beginning (roughly) of the script, which is used while running your application server.
For tomcat its catalina.sh
For Jboss AS its run.sh
For weblogic its setDomainEnv.sh
And After doing that start your server and deploy your application. Finally, your #Scheduled method should know the information it needs. As the property file is outside of the application, you can change the value of the property when you want without rebuilding the application or without even disturbing it!
just add this code in your web.xml
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>my.root.path</param-value>
</context-param>
and use it your code as a system properties

Accessing JNDI from within Eclipse OSGI bundle, hosted in WebSphere App Server

I have a problem accessing JNDI resources from within an OSGI bundle, hosted in
WebSphere Application Server (WAS) using a servlet bridge.
It is failing on creating the JNDI initial context. My code is:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.ibm.websphere.naming.WsnInitialContextFactory");
InitialContext ctx = new InitialContext(env);
This fails with:
javax.naming.NoInitialContextException:
Failed to create InitialContext using factory specified in hashtable {java.naming.provider.url=corbaloc:rir:/NameServiceServerRoot, java.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory, java.naming.factory.url.pkgs=com.ibm.ws.naming:com.ibm.ws.runtime:com.ibm.iscportal.jndi} [Root exception is java.lang.NullPointerException]
When I run the same code directly within a WAR module (not using OSGI), it is successful. I assume therefore the problem is something about accessing JNDI from within OSGI.
I have seen some references to Class Loader problems when accessing JNDI from within OSGI ... not sure if this is my problem, since the above exception does not explicitly relate to class loading, but maybe it is. Anyhow, if this is the problem, I am not sure how to fix it!
Is it in fact possible to access JNDI and JDBC entries set up within WAS, from within my OSGI module?
My application is an Eclipse RAP (Rich Ajax Plugin), packaged into a WAR file using the Eclipse WAR Product Tooling described at:
http://eclipsesource.com/blogs/2010/08/17/equinoxrap-war-deployment-an-end-to-the-pain/
This works successfully so far, apart from the JNDI access.
Many thanks
David
By default the thread context classloader will be used to load the InitialContextFactory. This is probably (but no guarantee) your bundle's classloader. You have a couple of options:
Configure the org.osgi.framework.bootdelegation property. This is probably implicitly set to sun.,com.sun. so you want to change it to be sun.,com.sun.,com.ibm.websphere.naming.* I believe this can be set in the servlet bridge wars WEB-INF/launch.ini
You could also import comibm.websphere.naming which would require you to add to the launch.ini org.osgi.framework.system.packages.extra=com.ibm.websphere.naming
Either should work.
Good luck.

Resources