[jboss-jira] [JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
Paulo Silva (JIRA)
issues at jboss.org
Fri Jun 8 07:39:00 EDT 2018
Paulo Silva created WFLY-10539:
----------------------------------
Summary: ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
Key: WFLY-10539
URL: https://issues.jboss.org/browse/WFLY-10539
Project: WildFly
Issue Type: Bug
Components: Web (Undertow)
Affects Versions: 13.0.0.Final, 12.0.0.Final
Reporter: Paulo Silva
Assignee: Stuart Douglas
After several tests I've found that ServletContainerInitializer instances aren't being called in a deterministic order, even when an absolute-ordering is configured in web.xml.
Stepping through the code, on wildfly startup, I've found that ServletContainerInitializer instances are being collected to ScisMetaData.The problem is that they are being stored in a HashSet, and that makes no guarantees of the iteration order!
The set is being initialized here:
{code:java}
Set<ServletContainerInitializer> scis = scisMetaData.getScis();
Set<Class<? extends ServletContainerInitializer>> sciClasses = new HashSet<>();
if (scis == null) {
scis = new HashSet<ServletContainerInitializer>();
scisMetaData.setScis(scis);
}
{code}
And the ServletContainerInitializer implementations that are found in jars are being added here:
{code:java}
// Find local ServletContainerInitializer services
List<String> order = warMetaData.getOrder();
Map<String, VirtualFile> localScis = warMetaData.getScis();
if (order != null && localScis != null) {
for (String jar : order) {
VirtualFile sci = localScis.get(jar);
if (sci != null) {
scis.addAll(loadSci(classLoader, sci, jar, true, sciClasses));
}
}
}
{code}
and later iterated and added to the DeployementInfo here (they are added to a List!):
{code:java}
if (scisMetaData != null && scisMetaData.getHandlesTypes() != null) {
for (final ServletContainerInitializer sci : scisMetaData.getScis()) {
final ImmediateInstanceFactory<ServletContainerInitializer> instanceFactory = new ImmediateInstanceFactory<>(sci);
d.addServletContainerInitalizer(new ServletContainerInitializerInfo(sci.getClass(), instanceFactory, scisMetaData.getHandlesTypes().get(sci)));
}
}
{code}
+But+, since scisMetaData.getScis() returns a HashSet, there is absolutely no guarantee that the iteration order is the same as the insertion order (the order that is imposed by warMetaData.getOrder()).
So a simple fix is to use a LinkedHashSet instead of a HashSet:
The ServletContainerInitializer instances are later iterated (List iteration) and called in DeployementManagerImpl:
{code:java}
//then run the SCI's
for (final ServletContainerInitializerInfo sci : deploymentInfo.getServletContainerInitializers()) {
final InstanceHandle<? extends ServletContainerInitializer> instance = sci.getInstanceFactory().createInstance();
try {
instance.getInstance().onStartup(sci.getHandlesTypes(), servletContext);
} finally {
instance.release();
}
}
{code}
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
More information about the jboss-jira
mailing list