Tomcat 8 Slow startup with deployWAR - performance

I went from Tomcat 7.0.54 to 8.0.15, upgraded openSSL to 1.0.1k and tcnative to the latest 1.1.32 with APR 1.5.1.
However, Tomcat now starts about 2 to 3 times slower than before. Most noticeably, it takes alot longer to deploy WAR files.
Tomcat 7
Jan 20, 2015 3:39:36 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deployment of web application archive <PATH>\file.war has finished in 433 ms
Tomcat 8
Jan 21, 2015 2:27:01 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deployment of web application archive <PATH>\file.war has finished in 4,310 ms
This happens to all WAR files, all went from milliseconds to around 5 seconds.
I removed the JasperListener from the server.xml because it appears to have been removed.
unpackWARs="false"
autoDeploy="true"
unpackWars does not make a difference if set to true (atleast not noticable).
I thought it might have been the annotation scanning issue fixed in 8.0.17, but no luck.
I noticed that jarsToSkip in catalina.properties changed from
tomcat.util.scan.DefaultJarScanner.jarsToSkip to
tomcat.util.scan.StandardJarScanFilter.jarsToSkip
and that
org.apache.catalina.startup.TldConfig.jarsToSkip was removed and went to context.xml
<JarScanner>
<JarScanFilter tldSkip="websocket-api.jar,tomcat-websocket.jar"/>
</JarScanner>
However, none of this seems to bring me back to the performance of tomcat 7. The one action that did do it, was removing the websocket jars. However we need them. This brings me to the conclusion that they are still scanned, even though they should be skipped.
Am I missing something? Does the context.xml not do the same as the catalina.properties jarsToSkip?

The solution for slow startup in general for me was to put
in conf/context.xml:
<Context>
<JarScanner>
<JarScanFilter defaultPluggabilityScan="false" />
</JarScanner>
</Context>
Source:
https://groups.google.com/a/apereo.org/forum/#!topic/sakai-dev/cjtYGxd6hG0
EDIT Oct-2022:
Adding a scanManifest="false" attribute to <JarScanner> tag may speed up the loading process even further:
<JarScanner scanManifest="false">
<JarScanFilter defaultPluggabilityScan="false" />
</JarScanner>

Are you sure unpackWARs="true" is not making a difference for you?
There's an ongoing discussion about this topic in bugzilla:
https://issues.apache.org/bugzilla/show_bug.cgi?id=57251
There it has been established that Tomcat 8's behaviour when unpackWARs="false" will be noticeably slower because of an implementation simplification performed in the code.

I am having similar problems here.
One option that improved the startup time was to add:
metadata-complete="true"
to the web.xml (webapp element), as recommended in https://cwiki.apache.org/confluence/display/TOMCAT/HowTo+FasterStartUp. This assumes your web.xml is all what your web-app needs to boot.
It didn't totally fix the issue for me, but startup speed improvement was substantial.

you can try parallelism for startup by changing
in conf/server.xml
host element attribute <Host ... startStopThreads="0"/>

Related

Frustrated with configuring Tomcat v8 jdbc pool for Oracle 19c

We have an older application on Linux Tomcat v8, connecting to Oracle 19c database using Oracle 19c jdbc client library ojdbc8.jar and having trouble getting the right datasource settings in context.xml
Much of the online resources I've found are contradictory, but this is where I'm at right now:
<Resource
name="jdbc/myDatasource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#ldap://{LDAP_HOST}:389/{DBNAME},cn=OracleContext,dc={DOMAIN},dc=com"
username="*********"
password="*********"
maxTotal="50"
maxIdle="10"
connectionProperties="oracle.jdbc.ReadTimeout=5000"
/>
But I'm not trusting that we're using the right factory, since the classloader logging shows this:
[Loaded org.apache.tomcat.jdbc.pool.DataSourceFactory from file:/opt/apache-tomcat/apache-tomcat-8.5.31/lib/tomcat-jdbc.jar]
[Loaded org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory from file:/opt/apache-tomcat/apache-tomcat-8.5.31/lib/tomcat-dbcp.jar]
Feb 01, 2023 11:30:50 AM org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory getObjectInstance
Feb 01, 2023 11:30:53 AM org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory getObjectInstance
Feb 01, 2023 11:30:53 AM org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory getObjectInstance
It seems like the right factory gets loaded, but then the basic/default factory is being used to create the pools instead of the Tomcat DataSourceFactory. Am I reading this wrong?
Any pointers that I should look for? I'm scanning the application contents under /webapps to see if they have any embedded jdbc pools being created, but so far haven't found anything.
We're not trying to do anything fancy, we just want the basic/right/normal settings to start with for this connection scenario. All the settings we have now were passed down from previous Tomcat & Oracle versions, so everything is suspect.
Edited to add:
I found this buried in the application code, and when I comment it out I can see the "Basic" DataSourceFactory is no longer loaded, and the messages about the getObjectInstance are gone.
<resource-ref id="ResourceRef_1200664413729">
<description>data source</description>
<res-ref-name>jdbc/masked-name</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
But now if I specify the Tomcat factory for my context.xml datasources:
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
then we get bad pool behavior in a failover situation. The pool appears to get corrupted when one DB node goes down, requiring a restart.
But if I specify no factory, then the log again shows the DB2 BASIC factory being used, yet things seem to work right for failover.
So I don't understand why all the online documents seem to want me to use the Tomcat datasource factory. What's "right" ?

EMF2DOMAdapterImpl_ERROR_0 Websphere Application Server WAS (V8.5) DeploymentDescriptorLoadException: WEB-INF/web.xml

Websphere Application Server V 8.5 fails to startup with certain web.xml structure.
Current DOCTYPE uses http://java.sun.com/dtd/web-app_2_3.dtd .
This error mainly occurs when there is a problem with the web.xml deployment descriptor.
This problem is caused because of invalid tag in the web.xml which can be due to multiple different things such as:
There should be no duplicate tages for
session-config
welcome-file-list
jsp-config
login-config
locale-encoding-mapping-list
Web.xml is not supposed to have multiple url-pattern under one servlet-mapping tag in deployment descriptor. If you have around 3 - 4 url-patterns under one servlet-mapping, move this to multiple servlet mapping containing one url-patterns.
For more debug information you can check the logs in AppServer\profiles\AppSrv01\logs\server1\SystemErr

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!

Request does not contain Security header, but it's a fault CXF STS Service Client error

I am getting error as provided below:
Jul 06, 2014 3:52:02 PM org.apache.cxf.ws.addressing.soap.MAPCodec restoreExchange WARNING: Response message does not contain WS-Addressing properties. Not correlating response.
Jul 06, 2014 3:52:02 PM org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor handleMessage
WARNING: Request does not contain Security header, but it's a fault.
Jul 06, 2014 3:52:03 PM org.apache.cxf.ws.addressing.ContextUtils retrieveMAPs
WARNING: WS-Addressing - failed to retrieve Message Addressing Properties from context
Exception in thread "main" org.apache.cxf.binding.soap.SoapFault: The signature or decryption was invalid
at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:84)
I have some complete example at https://github.com/sampleref/CXFSecurity Please suggest some inputs as it is important for me. Also full details can be found at CXF STS client throws Request does not contain Security header/Response message does not contain WS-Addressing properties
Thanks
I'll put this answer for anyone else who Googles this error and arrives here.
I had the same problem with a JSF2 maven web application running on JBoss Applicatoin server, but I imagine it might happen for many other types of web apps using servlet containers for token-based security (i.e. SAML).
Simply make sure that any passwords you store in configuration files (mine was in standalone.xml) to utilise token-based security are not changed or updated, otherwise this error will occur.

filter-name element is missing in generated web.xml

One of our old applications uses Struts-1.2 and EJB-2, generated with xdoclet 1.2.3. Maven 1 is used to build the application using java 1.4. The application has been running in weblogic 8.1 without any issues.
Now we are upgrading to Weblogic 10.3.6 which runs on java 6. When the application is deployed to Weblogic 10.3.6 we encounter the following error.
The error is weblogic.descriptor.DescriptorException: VALIDATION PROBLEMS WERE FOUND problem:
cvc-minLength-valid.1.1: string length (0) is less than minLength facet (1) for filter-nameType
in namespace http://java.sun.com/xml/ns/javaee:<null>
I understand this error is because the web.xml file is missing the filter-name element for a Filter class.
The problem is web.xml is generated by the application as part of the build process and I have no idea where or how to add the filter-name element value. What should I do to get the filter-name element to be added to the generated web.xml?
(Note: There is no problem when deployed to Weblogic8.1. This happens only when trying to deploy on weblogic10.3.6.)
Any help will be much appreciated.
Thanks.
Got it going.
I had to add the following annotation to the filter class...
#web.filter name="FilterClassName"
web.xml generated the filter-name element after I added the above annotation.

Resources