[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:40:00 EDT 2018
[ https://issues.jboss.org/browse/WFLY-10539?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
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)
More information about the jboss-jira
mailing list