Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@

/**
* Disable Scalar WebJar AutoConfiguration.
*
* <p>The class stays in this module, because it is shared by both Springdoc Scalar starters, but it
* is no longer registered here. This module is a dependency of every starter, so a registration
* here made the filter apply to applications using the Swagger UI or the API-only starter as well,
* leaving them with neither Scalar controller (#3387). Each Springdoc Scalar starter now declares
* the filter in its own {@code META-INF/spring.factories}, which keeps the duplicate registration
* protection of #3084 while letting the standalone Scalar integration work everywhere it is not
* replaced.
*
* <p>Both Scalar auto-configurations are always excluded together, by design: Scalar's own
* {@code ScalarWebFluxAutoConfiguration} carries no {@code @ConditionalOnWebApplication}
* constraint, so excluding only the matching stack would let a reactive Scalar controller be
* registered in a servlet application, and the other way round.
*/
public class ScalarDisableAutoConfiguration
implements AutoConfigurationImportFilter {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
*
* *
* * *
* * * *
* * * * *
* * * * * * Copyright 2019-2026 the original author or authors.
* * * * * *
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * * you may not use this file except in compliance with the License.
* * * * * * You may obtain a copy of the License at
* * * * * *
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * * *
* * * * * * Unless required by applicable law or agreed to in writing, software
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * * See the License for the specific language governing permissions and
* * * * * * limitations under the License.
* * * * *
* * * *
* * *
* *
*
*/

package org.springdoc.scalar;

import java.util.List;

import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.core.io.support.SpringFactoriesLoader;

import static org.assertj.core.api.Assertions.assertThat;

/**
* springdoc-openapi-starter-common is pulled in by every starter: nothing that disables Scalar's
* standalone autoconfiguration may be registered from here, otherwise applications using the
* Swagger UI or the API-only starter lose the Scalar integration with nothing replacing it (#3387).
* The filter itself must keep excluding both Scalar auto-configurations, since it is the guard
* against the duplicate registration of #3084 once a Springdoc Scalar starter declares it.
*
* @author awinishere
*/
class ScalarDisableAutoConfigurationTest {

private static final String FILTER_CLASS = "org.springdoc.scalar.ScalarDisableAutoConfiguration";

private static final String[] SCALAR_AUTO_CONFIGURATIONS = {
"com.scalar.maven.webmvc.ScalarWebMvcAutoConfiguration",
"com.scalar.maven.webflux.ScalarWebFluxAutoConfiguration" };

private List<String> registeredFilterNames() {
SpringFactoriesLoader loader = SpringFactoriesLoader
.forDefaultResourceLocation(getClass().getClassLoader());
return loader.load(AutoConfigurationImportFilter.class)
.stream()
.map(filter -> filter.getClass().getName())
.toList();
}

@Test
void noScalarAutoConfigurationImportFilterIsRegisteredFromThisModule() {

assertThat(registeredFilterNames()).doesNotContain(FILTER_CLASS);
}

@Test
void filterStillDisablesBothScalarAutoConfigurations() {

boolean[] matches = new ScalarDisableAutoConfiguration()
.match(SCALAR_AUTO_CONFIGURATIONS, (AutoConfigurationMetadata) null);

assertThat(matches).containsExactly(false, false);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
*
* *
* * *
* * * *
* * * * *
* * * * * * Copyright 2019-2026 the original author or authors.
* * * * * *
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * * you may not use this file except in compliance with the License.
* * * * * * You may obtain a copy of the License at
* * * * * *
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * * *
* * * * * * Unless required by applicable law or agreed to in writing, software
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * * See the License for the specific language governing permissions and
* * * * * * limitations under the License.
* * * * *
* * * *
* * *
* *
*
*/

package test.org.springdoc.webflux.scalar;

import java.util.List;

import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.core.io.support.SpringFactoriesLoader;

import static org.assertj.core.api.Assertions.assertThat;

/**
* The exclusion of Scalar's standalone auto-configuration belongs to the Scalar starters: it is
* only legitimate where a Springdoc Scalar controller replaces it (#3387). It is declared in this
* module {@code META-INF/spring.factories}, and not in springdoc-openapi-starter-common, so that
* it is loaded exactly when this starter is installed.
*
* @author awinishere
*/
class ScalarStarterRegistersTheDisableFilterTest {

@Test
void scalarStarterDisablesTheStandaloneAutoConfiguration() {

SpringFactoriesLoader loader = SpringFactoriesLoader
.forDefaultResourceLocation(getClass().getClassLoader());

List<String> registeredFilters = loader.load(AutoConfigurationImportFilter.class)
.stream()
.map(filter -> filter.getClass().getName())
.toList();

assertThat(registeredFilters).contains("org.springdoc.scalar.ScalarDisableAutoConfiguration");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springdoc.scalar.ScalarDisableAutoConfiguration
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
*
* *
* * *
* * * *
* * * * *
* * * * * * Copyright 2019-2026 the original author or authors.
* * * * * *
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * * you may not use this file except in compliance with the License.
* * * * * * You may obtain a copy of the License at
* * * * * *
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * * *
* * * * * * Unless required by applicable law or agreed to in writing, software
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * * See the License for the specific language governing permissions and
* * * * * * limitations under the License.
* * * * *
* * * *
* * *
* *
*
*/

package test.org.springdoc.webmvc.scalar;

import java.util.List;

import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.core.io.support.SpringFactoriesLoader;

import static org.assertj.core.api.Assertions.assertThat;

/**
* The exclusion of Scalar's standalone autoconfiguration belongs to the Scalar starters: it is
* only legitimate where a Springdoc Scalar controller replaces it (#3387). It is declared in this
* module {@code META-INF/spring.factories}, and not in springdoc-openapi-starter-common, so that
* it is loaded exactly when this starter is installed.
*
* @author awinishere
*/
class ScalarStarterRegistersTheDisableFilterTest {

@Test
void scalarStarterDisablesTheStandaloneAutoConfiguration() {

SpringFactoriesLoader loader = SpringFactoriesLoader
.forDefaultResourceLocation(getClass().getClassLoader());

List<String> registeredFilters = loader.load(AutoConfigurationImportFilter.class)
.stream()
.map(filter -> filter.getClass().getName())
.toList();

assertThat(registeredFilters).contains("org.springdoc.scalar.ScalarDisableAutoConfiguration");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
*
* *
* * *
* * * *
* * * * *
* * * * * * Copyright 2019-2026 the original author or authors.
* * * * * *
* * * * * * Licensed under the Apache License, Version 2.0 (the "License");
* * * * * * you may not use this file except in compliance with the License.
* * * * * * You may obtain a copy of the License at
* * * * * *
* * * * * * https://www.apache.org/licenses/LICENSE-2.0
* * * * * *
* * * * * * Unless required by applicable law or agreed to in writing, software
* * * * * * distributed under the License is distributed on an "AS IS" BASIS,
* * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * * * * * See the License for the specific language governing permissions and
* * * * * * limitations under the License.
* * * * *
* * * *
* * *
* *
*
*/

package test.org.springdoc.webmvc.scalar.app20;

import com.scalar.maven.webmvc.ScalarWebMvcAutoConfiguration;
import com.scalar.maven.webmvc.ScalarWebMvcController;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;

/**
* The Springdoc Scalar starter and Scalar's own integration both declare a bean named
* {@code scalarWebMvcController} mapped to {@code ${scalar.path}}: the standalone one must not
* survive next to the Springdoc controller, otherwise the application fails on a duplicated bean
* definition (#3084). This is the counterpart of the standalone Scalar support restored by #3387.
*
* @author awinishere
*/
@SpringBootTest
class SpringDocApp20Test {

@Autowired
private ApplicationContext context;

@Test
void scalarStandaloneAutoConfigurationIsNotApplied() {

assertThat(context.getBeanNamesForType(ScalarWebMvcAutoConfiguration.class)).isEmpty();
assertThat(context.getBeanNamesForType(ScalarWebMvcController.class)).isEmpty();
}

@Test
void springdocScalarControllerReplacesIt() {

assertThat(context.getBean("scalarWebMvcController"))
.isInstanceOf(org.springdoc.webmvc.scalar.ScalarWebMvcController.class);
}

@SpringBootApplication
static class SpringDocTestApp {}
}