Just a quick clarification.
The goal of metadata-complete="true" is to say that the metadata in the web.xml is complete.
It has no effect on the scanning or not classpath information in WEB-INF/classes and WEB-INF/lib
Here's 2 examples where scanning is still required, regardless of what metadata-complete says.
1) ServletContainerInitializer
In order to support this, the services for these are looked up from META-INF/services/javax.servlet.ServletContainerInitializer and instantiated.
Then any @HandlesTypes annotations on these SCI implementations are identified.
All of the HandlesTypes entries are then required to be scanned for in the WEB-INF/classes and WEB-INF/lib tree.
Then the server calls the SCI.onStartup(Set<Class<?>>, ServletContext) with the entire set of classes matching the @HandlesTypes entries.
2) JSR-356 javax.websocket @ServerEndpoint and ServerApplicationConfig support.
When you have websocket endpoints in the mix, they have to be scanned for in order to be installed.
When you have ServerApplicationConfig instances, those have to be invoked to (potentially) filter the found endpoints from the scan.
In short, don't rely on metadata-complete="true" to mean "will not scan WEB-INF/classes and WEB-INF/lib jars".
That's simply not true (anymore)