问题
I'm super new to all of these frameworks so please try and bear with me here with what feels like should be a super simple thing.
I'm trying to learn the process of integrating Swagger into an existing Dropwizard application to generate the API documentation, ideally using the Swagger UI interface so that it's interactive for people trying to use/learn it. Specifically, using this bundle: smoketurner/dropwizard-swagger
Before trying to wrestle with the full sized project my employer wants it integrated with, I tried adding it into the standard Dropwizard example application, thinking that should be a hassle-free jumping off point. After following the instructions on the github page for the bundle, I'm hit by the following error:
Test set: com.example.helloworld.IntegrationTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 2.003 s <<< FAILURE! - in com.example.helloworld.IntegrationTest
com.example.helloworld.IntegrationTest Time elapsed: 2.003 s <<< ERROR!
java.lang.IllegalStateException: You need to provide an instance of SwaggerBundleConfiguration
What am I missing?
Below are the Configuration and Application files in question, with the additions made as per the github bundle instructions.
HelloWorldConfiguration:
package com.example.helloworld;
import com.example.helloworld.core.Template;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
import io.dropwizard.Configuration;
import io.dropwizard.db.DataSourceFactory;
import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.Map;
public class HelloWorldConfiguration extends Configuration {
@NotEmpty
private String template;
@NotEmpty
private String defaultName = "Stranger";
@JsonProperty("swagger")
public SwaggerBundleConfiguration swaggerBundleConfiguration;
@Valid
@NotNull
private DataSourceFactory database = new DataSourceFactory();
@NotNull
private Map<String, Map<String, String>> viewRendererConfiguration = Collections.emptyMap();
@JsonProperty
public String getTemplate() {
return template;
}
@JsonProperty
public void setTemplate(String template) {
this.template = template;
}
@JsonProperty
public String getDefaultName() {
return defaultName;
}
@JsonProperty
public void setDefaultName(String defaultName) {
this.defaultName = defaultName;
}
public Template buildTemplate() {
return new Template(template, defaultName);
}
@JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
return database;
}
@JsonProperty("database")
public void setDataSourceFactory(DataSourceFactory dataSourceFactory) {
this.database = dataSourceFactory;
}
@JsonProperty("viewRendererConfiguration")
public Map<String, Map<String, String>> getViewRendererConfiguration() {
return viewRendererConfiguration;
}
@JsonProperty("viewRendererConfiguration")
public void setViewRendererConfiguration(Map<String, Map<String, String>> viewRendererConfiguration) {
final ImmutableMap.Builder<String, Map<String, String>> builder = ImmutableMap.builder();
for (Map.Entry<String, Map<String, String>> entry : viewRendererConfiguration.entrySet()) {
builder.put(entry.getKey(), ImmutableMap.copyOf(entry.getValue()));
}
this.viewRendererConfiguration = builder.build();
}
}
HelloWorldApplication:
package com.example.helloworld;
import com.example.helloworld.auth.ExampleAuthenticator;
import com.example.helloworld.auth.ExampleAuthorizer;
import com.example.helloworld.cli.RenderCommand;
import com.example.helloworld.core.Person;
import com.example.helloworld.core.Template;
import com.example.helloworld.core.User;
import com.example.helloworld.db.PersonDAO;
import com.example.helloworld.filter.DateRequiredFeature;
import com.example.helloworld.health.TemplateHealthCheck;
import com.example.helloworld.resources.FilteredResource;
import com.example.helloworld.resources.HelloWorldResource;
import com.example.helloworld.resources.PeopleResource;
import com.example.helloworld.resources.PersonResource;
import com.example.helloworld.resources.ProtectedResource;
import com.example.helloworld.resources.ViewResource;
import com.example.helloworld.tasks.EchoTask;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.auth.AuthDynamicFeature;
import io.dropwizard.auth.AuthValueFactoryProvider;
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
import io.dropwizard.configuration.EnvironmentVariableSubstitutor;
import io.dropwizard.configuration.SubstitutingSourceProvider;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.hibernate.HibernateBundle;
import io.dropwizard.migrations.MigrationsBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.dropwizard.views.ViewBundle;
import io.federecio.dropwizard.swagger.SwaggerBundle;
import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
import java.util.Map;
public class HelloWorldApplication extends Application<HelloWorldConfiguration> {
public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
}
private final HibernateBundle<HelloWorldConfiguration> hibernateBundle =
new HibernateBundle<HelloWorldConfiguration>(Person.class) {
@Override
public DataSourceFactory getDataSourceFactory(HelloWorldConfiguration configuration) {
return configuration.getDataSourceFactory();
}
};
@Override
public String getName() {
return "hello-world";
}
@Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
// Enable variable substitution with environment variables
bootstrap.setConfigurationSourceProvider(
new SubstitutingSourceProvider(
bootstrap.getConfigurationSourceProvider(),
new EnvironmentVariableSubstitutor(false)
)
);
bootstrap.addCommand(new RenderCommand());
bootstrap.addBundle(new AssetsBundle());
bootstrap.addBundle(new MigrationsBundle<HelloWorldConfiguration>() {
@Override
public DataSourceFactory getDataSourceFactory(HelloWorldConfiguration configuration) {
return configuration.getDataSourceFactory();
}
});
bootstrap.addBundle(hibernateBundle);
bootstrap.addBundle(new ViewBundle<HelloWorldConfiguration>() {
@Override
public Map<String, Map<String, String>> getViewConfiguration(HelloWorldConfiguration configuration) {
return configuration.getViewRendererConfiguration();
}
});
bootstrap.addBundle(new SwaggerBundle<HelloWorldConfiguration>() {
@Override
protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(HelloWorldConfiguration configuration) {
return configuration.swaggerBundleConfiguration;
}
});
}
@Override
public void run(HelloWorldConfiguration configuration, Environment environment) {
final PersonDAO dao = new PersonDAO(hibernateBundle.getSessionFactory());
final Template template = configuration.buildTemplate();
environment.healthChecks().register("template", new TemplateHealthCheck(template));
environment.admin().addTask(new EchoTask());
environment.jersey().register(DateRequiredFeature.class);
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(new ExampleAuthenticator())
.setAuthorizer(new ExampleAuthorizer())
.setRealm("SUPER SECRET STUFF")
.buildAuthFilter()));
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
environment.jersey().register(RolesAllowedDynamicFeature.class);
environment.jersey().register(new HelloWorldResource(template));
environment.jersey().register(new ViewResource());
environment.jersey().register(new ProtectedResource());
environment.jersey().register(new PeopleResource(dao));
environment.jersey().register(new PersonResource(dao));
environment.jersey().register(new FilteredResource());
}
}
回答1:
For anyone else trying to learn this and struggling, the issue was that the included test suite in the sample application has its own YML file, test-example.yml
that you also need to add the swagger properties into. This will allow the tests to pass and everything should go smoothly from there.
Added properties to test-example.yml
:
swagger:
resourcePackage: com.example.helloworld.resources
来源:https://stackoverflow.com/questions/50569273/adding-swagger-to-dropwizard-application-need-to-provide-instance-of-swaggerbun