I have a Spring Rest controller and its NOT spring boot application. Its just a REST API Project. I want to integrate swagger2 in my project. I tried all the examples in Net and in demo but with no luck. When i try to execute http://localhost:8085/context/swagger-ui.html i get 404 error. Please find my confugration below and let me know if there is any discrepencies. Any help is highly appreciated.
jars - under /WEB-INF/lib
google-collections-1.0.jar
springfox-core-2.2.2.jar
springfox-schema-2.2.2.jar
springfox-spi-2.2.2.jar
springfox-spring-web-2.2.2.jar
springfox-staticdocs-2.2.2.jar
springfox-swagger-common-2.2.2.jar
springfox-swagger-ui-2.2.2.jar
springfox-swagger2-2.2.2.jar
My swagger config class -
#EnableSwagger2
public class SwaggerConfiguration {
}
My springconfig class
#EnableWebMvc
#ComponentScan(basePackageClasses = controller.class)
#Import(SwaggerConfiguration.class)
public class SpringConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
My Application initializer class below as per springfox-java demo . I tried with and without the below class and its not working either way.
Application Initializer class
public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{controller.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/*"};
}
}
I can access my rest urls but not swagger-ui.html in the same context.
Please let me know what i am missing here?
I add the manual selection of controllers:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket productApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("my.package.to.api"))
.paths(regex("/product.*")) //optional
.build();
}
}
given details are not sufficient to reproduce/analyse the issue.
But, today I faced similar problem, ofcourse used SpringBoot, and solved myself as below:
as my sample have one controller class and an application class having main method, I created packages as below, and it got solved:
hello
controllers
HelloController
swagger
SwaggerConfig2
HelloApplication
Related
I'm developing a jar library and trying to inject an interceptor from external jar library to Application.
For example:
External Lib
MyExternalInterceptor.java
public class MyExternalInterceptor implements HandlerInterceptor {
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// Do something
}
}
I tried to using AOP in external libs but it's not working.
InterceptorAspect.java
#Around("execution(* org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.addInterceptors(..))")
public Object aspect(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// Tried to inject MyExternalInterceptor here
Object result = proceedingJoinPoint.proceed();
return result;
}
In Application using that lib:
Application
MyConfiguration.java
#Configuration
public MyConfiguration extends WebMvcConfigurationSupport {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SpringTestInterceptor()); // client's own interceptor
/* Add MyExternalInterceptor not explicitly but implicitly using AOP or other things */
}
}
Is there any way to inject an interceptor from external lib to App?
I know the question is very obscure (sorry for that), but could you give me any advice or hint to make it work?
Thank you for anyone who read my question :)
(I updated few more details for clarification)
Summary
Use WebMvcConfigurer in both Client and library side instead of WebMvcConfigurationSupport
AoP is not needed
I use WebMvcConfigurer instead of WebMvcConfigurationSupport and change some codes like below:
External Lib
MyExternalInterceptor.java
Same as before
InterfaceAspect.java
Don't needed it anymore
MyExternalLibConfiguration.java
#Configuration
public class MyExternalLibConfiguration implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyExternalInterceptor());
}
}
Application (client)
MyConfiguration.java
#Configuration
public MyConfiguration implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SpringTestInterceptor()); // client's own interceptor
/* No need to add MyExternalInterceptor in here */
}
}
That's all! Everything is working well as M. Deinum said in comment.
Thank you again Deinum!
In my older Spring 4 web-app, I used an applicationContext.xml file, and my default spring profile was as follows;
<beans profile="default">
<context:property-placeholder location="file:/opt/myapp/myapp-ws.properties" />
</beans>
And now I am using Spring 5 Framework, but NOT Spring Boot 2.x, and I want to do this in my Java Config class.
My main configuration class looks like this;
#Configuration
#ComponentScan(basePackages = "com.tomholmes.myapp")
#EnableWebMvc
public class MyAppConfig
{
}
And I have the AppInitializer as follows;
public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
private static final Log logger = LogFactory.getLog(ApplicationInitializer.class);
#Override
protected Class<?>[] getRootConfigClasses()
{
return new Class[]
{ MyAppConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses()
{
return new Class[]{};
}
#Override
protected String[] getServletMappings()
{
return new String[]
{ "/api/*" };
}
}
I've been doing some research on the Net since there is a lot of information on this, but a lot of it conflates Spring Boot,and I just want a Spring 5 without Spring Boot solution. I'll keep looking, I am sure this is a simple issue.
Thanks!
I believe something like this might do the trick:
#Configuration
public class PropertiesConfig {
#Bean
public PropertyPlaceholderConfigurer properties() {
final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
final List<Resource> resources = new ArrayList<>();
resources.add(new FileSystemResource("/etc/app/application-{profile_1}.properties"));
resources.add(new FileSystemResource("/etc/app/application-{profile_2}.properties"));
ppc.setLocations(resourceLst.toArray(new Resource[]{}));
return ppc;
}
Please note, that this is just the suggestion, this code is not tested.
Profile specific application properties should be resolved automatically by current active profile.
I haven't tested this, but a #Configuration class with both #Profile and #PropertySource should work:
#Configuration
#Profile("default")
#PropertySource("file:/opt/myapp/myapp-ws.properties")
public class MyappWebservicePropertyConfig {
}
I am using spring boot application mvc with graphDb (Neo4j) as my database.
And I have problem when I have to do internationalization for my app.
I have this code on my application.java
public class Application extends Neo4jConfiguration {
#Autowired
GraphDatabase graphDatabase;
#Bean
GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("my-graphdb");
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
When I tried to implement internationalization, the tutor says that I need to implement:
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
This code above need the class is extended by WebMvcConfigurerAdapter.
This is the problem, I didn't use WebMvcConfigurerAdapter so I cannot add the method above.
Do I have another option to make my internationalization work well with Neo4jConfiguration?
I just found out how to make it work.
I just have to add new file that extend WebMvcConfigurerAdapter and put the addInterceptors module into that new file.
Which tutorial are you referring to?
you can also create your own Neo4jConfiguration subclass and #Import it onto your boot application context
We are looking to migrate our project to Spring Boot. However it is unclear how to replicate the functionality of AbstractAnnotationConfigDispatcherServletInitializer in Spring Boot?
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
#Override
protected Class<?>[] getRootConfigClasses()
{
return new Class<?>[]{AppConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses()
{
return new Class<?>[]{WebappConfig.class};
}
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setAsyncSupported(true);
}
#Override
protected String[] getServletMappings()
{
return new String[]{"/"};
}
#Override
protected Filter[] getServletFilters()
{
DelegatingFilterProxy shiroFilter = new DelegatingFilterProxy("shiroFilter");
shiroFilter.setTargetFilterLifecycle(true);
CompositeFilter compositeFilter = new CompositeFilter();
compositeFilter.setFilters(ImmutableList.of(new CorsFilter(),shiroFilter));
return new Filter[]{compositeFilter};
}
}
The AppConfig and WebappConfig parent/child relationship can be handled by SpringApplicationBuilder, although you might also consider a flat hierarchy.
Assuming that you are going the whole hog, and running an embedded servlet container you can register Filters and Servlets directly as beans.
You can also use ServletRegistrationBean and FilterRegistrationBean if you need to set things such as setAsyncSupported. The final option is to add a bean that implements org.springframework.boot.context.embedded.ServletContextInitializer then do the registration yourself.
Something like this might get you a bit further:
#Bean
public ServletRegistrationBean dispatcherServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(
new DispatcherServlet(), "/");
registration.setAsyncSupported(true);
return registration;
}
#Bean
public Filter compositeFilter() {
CompositeFilter compositeFilter = new CompositeFilter();
compositeFilter.setFilters(ImmutableList.of(new CorsFilter(), shiroFilter));
return compositeFilter
}
Also, take a look at this section in the reference manual http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container
Well there is nothing special like just mark your AppInitializer with Boot annotations:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
...
}
I haven't tried it, but just combined the documentation:
Normally all the code from an existing WebApplicationInitializer can be moved into a SpringBootServletInitializer. If your existing application has more than one ApplicationContext (e.g. if it uses AbstractDispatcherServletInitializer) then you might be able to squash all your context sources into a single SpringApplication.
And SpringBootServletInitializer JavaDocs:
If your application is more complicated consider using one of the
other WebApplicationInitializers.
i am trying to combine a Spring Web Application (completed Annotation Based configuration, no xml configuration) with metrics 3.0.
I am running the application inside a jetty.
This is my current configuration for the default DispatcherServlet:
public class WebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
return new Filter[] { characterEncodingFilter };
}
}
This is the WebConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.rebuy.silo.amqpredelivery")
#EnableJpaRepositories(basePackages = "com.rebuy.silo.amqpredelivery.domain")
#EnableAspectJAutoProxy
#EnableTransactionManagement
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
jacksonConverter.setObjectMapper(objectMapper());
converters.add(jacksonConverter);
super.configureMessageConverters(converters);
}
#Bean
public ObjectMapper objectMapper() {
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssXXX");
format.setTimeZone(TimeZone.getTimeZone("GMT+1"));
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(format);
return mapper;
}
}
I want to add these two Servlets:
https://github.com/codahale/metrics/blob/master/metrics-servlets/src/main/java/com/codahale/metrics/servlets/HealthCheckServlet.java
https://github.com/codahale/metrics/blob/master/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java
What is the best way to do this? I think there should be some spring magic to make this extremly easy to do! But I was not able to find it :(
Thanks in advance
Björn
You can follow this codebase https://github.com/spiritedtechie/metrics-examples.
Or use this library called metrics-spring http://ryantenney.github.io/metrics-spring/
If you are using Spring and Metrics you should also be using #RyanTenney's Metrics-Spring module. It will simplify your Java config and make your Metrics usage much cleaner.
Take a look at the code behind the MetricsServlet and HealthCheckServlet. In my opinion its easier to just write your own Spring Controller to do the same thing than to figure out how to embed and wrap those old servlets.
Its easy!
Create a metrics specific config:
#Configuration
#EnableMetrics
public class MetricsConfig extends MetricsConfigurerAdapter {
#Override
public void configureReporters(MetricRegistry metricRegistry) {
registerReporter(ConsoleReporter
.forRegistry(metricRegistry)
.build()).start(5, TimeUnit.MINUTES);
}
}
And include it from your existing config by adding:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.rebuy.silo.amqpredelivery")
#EnableJpaRepositories(basePackages = "com.rebuy.silo.amqpredelivery.domain")
#EnableAspectJAutoProxy
#EnableTransactionManagement
#Import({MetricsConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {
...
The above config changes make it trivial to inject a MetricRegistry in any Spring component. All the MetricsServlet does is send the registry in response to the request. That is really easy to accomplish in a simple controller. For example:
#Controller
public class AdminMetricsController
{
#Autowired
MetricRegistry metricRegistry;
#RequestMapping(value = "/admin/metrics/", produces = {APPLICATION_JSON_VALUE})
public #ResponseBody MetricRegistry getMetrics(final HttpServletResponse response)
{
response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
return metricRegistry;
}
}
A HealthCheckRegistry can be injected in a similar way and another method added which would respond to /admin/health/ or whatever url you wanted.
Take a look at the following answer. It explains how to register a Servlet via JavaConfig:
Spring JavaConfig: Add mapping for custom Servlet