[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Description:
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. I've tested this in wildfly 10, 12 and 13.
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 as to 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 and called by insertion order (List iteration) 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}
was:
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. I've tested this in wildfly 10, 12 and 13.
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 as to 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}
> 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: 10.0.0.Final, 12.0.0.Final, 13.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. I've tested this in wildfly 10, 12 and 13.
> 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 as to 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 and called by insertion order (List iteration) 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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Description:
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. I've tested this in wildfly 10, 12 and 13.
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 as to 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}
was:
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. I've tested this in wildfly 10, 12 and 13.
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 as to 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}
> 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: 10.0.0.Final, 12.0.0.Final, 13.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. I've tested this in wildfly 10, 12 and 13.
> 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 as to 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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Description:
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. I've tested this in wildfly 10, 12 and 13.
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 as to 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}
was:
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. I've tested this in wildfly 10, 12 and 13.
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}
> 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: 10.0.0.Final, 12.0.0.Final, 13.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. I've tested this in wildfly 10, 12 and 13.
> 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 as to 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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Description:
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. I've tested this in wildfly 10, 12 and 13.
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}
was:
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}
> 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: 10.0.0.Final, 12.0.0.Final, 13.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. I've tested this in wildfly 10, 12 and 13.
> 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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Affects Version/s: 10.0.0.Final
> 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: 10.0.0.Final, 12.0.0.Final, 13.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. I've tested this in wildfly 10, 12 and 13.
> 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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Steps to Reproduce:
Define an absolute-ordering in web.xml and verify that ServletContainerInitializer
implementations aren't being called in the expected order ( warMetaData.getOrder() )
was:
Define an absolute-ordering in web.xml and verify that ServletContainerInitializer
implementations aren't being called in the expected order (warMetaData.getOrder()
> 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: 12.0.0.Final, 13.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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin... ]
Paulo Silva updated WFLY-10539:
-------------------------------
Workaround Description:
In ServletContainerInitializerDeploymentProcessor, update the following code to use a LinkedHashSet:
{code:java}
if (scis == null) {
scis = new LinkedHashSet<ServletContainerInitializer>();
scisMetaData.setScis(scis);
}
{code}
was:
In ServletContainerInitializerDeploymentProcessor, update the code to use a LinkedHashSet:
{code:java}
if (scis == null) {
scis = new LinkedHashSet<ServletContainerInitializer>();
scisMetaData.setScis(scis);
}
{code}
> 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: 12.0.0.Final, 13.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)
8 years, 1 month
[JBoss JIRA] (WFLY-10539) ServletContainerInitializer instances aren't invoked in the specified order (WarMetaData order)
by Paulo Silva (JIRA)
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)
8 years, 1 month