Using SpringFox to document my Spring RestController - java

I'm trying to use SpringFox to document a #RestController in my application but so far I've been met with stout resistance.
I've been following this example but whenever I start I get the following exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'documentationPluginsBootstrapper'
I know that's not much to go on so I managed to reproduce it on a pretty simple standalone application:
package example.swagger;
import org.springframework.boot.builder.SpringApplicationBuilder;
public class Main {
public static void main(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(AppConfig.class);
builder.child(SwaggerConfiguration.class).run(args);
}
}
The configuration classes used are as follows:
package example.swagger;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
#SpringBootApplication
public class AppConfig {
}
And finally:
package example.swagger;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
}
I've been struggling with this for days. Any help would be most appreciated! ;)

If I were to take a guess, it's probably because you are not running with the latest version of springfox. Could you try upgrading to 2.5.0. It may fix your problem.
PS: Don't have the link to the issue that fixes this handy, but I'll update this answer when I do.

Related

Debugging SpringBoot MVC service application 404 error

A web application I've been working on recently the past like 2 weeks maybe for whatever reason when I finally tested it - won't seem to even enter the method that I have to return a JSON list of objects. I have included the Jackson library and Spring Boot Web, Tomcat, Data-JPA, Hibernate, MySQL, and a library to allow me to access JSP files. The index.jsp comes up but I almost feel like Spring Boot is giving me that free of charge as it's not even entering that method. I have been having the issue for a few days but trying to resolve it on my own - I found another answer that suggested to put a breakpoint inside one of the Spring classes but when I "debugged" it through Eclipse, it didn't even stop at that class - something about pattern matching - One answer suggested adding a context to the application.properties file - didn't help. I've reduced it to as simple as I think I can get it. Can anyone tell me what I might be doing wrong? Before my code, the project is on Github at: https://github.com/sfulmer/Scheduler.git
Here's my controller:
package net.draconia.schedule.controllers;
import java.util.List;
import net.draconia.schedule.beans.Event;
import net.draconia.schedule.dao.EventDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class ScheduleController
{
private static final Logger logger = LoggerFactory.getLogger(ScheduleController.class);
#Autowired
private EventDAO mObjDAO;
protected EventDAO getDAO()
{
return(mObjDAO);
}
//#GetMapping("/events")
#RequestMapping(value = "events", method = RequestMethod.GET)
public #ResponseBody List<Event> getEvents()
{
logger.debug("I got here");
return(getDAO().getList());
}
#GetMapping("/")
public String index()
{
return("index");
}
}
Here is the DAO interface - I'll show the class if necessary but this is what the controller looks at:
package net.draconia.schedule.dao;
import java.util.List;
import javax.persistence.EntityNotFoundException;
import net.draconia.schedule.beans.Event;
public interface EventDAO
{
public Event getEventById(final long lId) throws EntityNotFoundException;
public List<Event> getList();
public void remove(final Event objEvent);
public void removeById(final long lId);
public Event save(final Event objEvent);
}
The Event class is so long but if I need to include it, I will. The application.properties file is here:
spring.datasource.url = jdbc:mysql://localhost:3306/schedule
spring.datasource.username = root
spring.datasource.password = R3g1n# M1lL$ 1$ My Qu3eN!
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
server.servlet.contextPath=/scheduler
and here is my Application class(with the SpringBootApplication annotation):
package net.draconia.schedule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#SpringBootApplication(scanBasePackages = {"net.draconia.schedule.controller"})
public class ScheduleApp implements WebMvcConfigurer
{
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)
{
return(builder.sources(ScheduleApp.class));
}
public static void main(String[] args)
{
SpringApplication.run(ScheduleApp.class, args);
}
}
I'm relatively new to Spring Boot but haven't ever ran into this problem ever before as I work with it at work and it works fine but we use entirely REST services there and I am using JSP files as well as sorta end-points that respond with JSON but you can't respond from REST services with JSP views so unfortunately I can't copy work's project to get that working or I would sigh Any thoughts on how I can get this working or what I am omitting?
My guess is that you're mixing things from Spring and Spring boot, and that's getting problems on loading beans, as you're probably changing the annotations load order or loading other beans rather than spring boot defaults as expected. For example, you implements WebMvcConfigurer, but you aren't providing any WebMvc Configuration, like a ViewResolver bean
My advice is to follow this guide: https://spring.io/guides/gs/spring-boot/
and use only the annotations from spring boot if using spring boot, or spring if using spring (they're similar, but not exactly the same, configuration is different).
Anyways, you can check loaded beans in Spring application context (Inject it in Application class) with ctx.getBeanDefinitionNames() method and see if your controller is there (i guess not).
By looking into code, my first impression is that, you have some typo in here:
#SpringBootApplication(scanBasePackages = {"net.draconia.schedule.controller"})
Your controller class package name has net.draconia.schedule.controllers.
So can you please correct your scanBasePackages with proper package name.
If that is not the case, please update full stack trace along with GET request which you are submitting into application. Will take a look & update answer accordingly.

Field repository in '' required a bean named 'entityManagerFactory' that could not be found

So I've been learning Spring for a few weeks. I am trying to make a simple project involving a Controller -> Service -> Repository -> Database pattern.
I started having this problem, but could not find the solution to it. I stumbled upon some similar problems online with the same error, but none of them gave my solution, everything seems normal in my project.
This is the error on output:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field repository in com.Library.services.LibraryService required a bean named 'entityManagerFactory' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
This are the files of my project (file tree):
This is my code:
Main class:
package com.Library;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
#EntityScan("com.Library.services")
#EnableJpaRepositories("com.Library.repositories")
public class LibraryApplication {
public static void main(String[] args) {
SpringApplication.run(LibraryApplication.class, args);
}
}
Model:
package com.Library.models.dtos;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
#Getter
#Setter
#Entity
public class BookCategory {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String Name;
}
Repository:
package com.Library.repositories;
import com.Library.models.dtos.BookCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface BookCategoryRepository extends JpaRepository<BookCategory,Long> {
List<BookCategory> findAll();
}
Service:
package com.Library.services;
import com.Library.models.dtos.BookCategory;
import com.Library.repositories.BookCategoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class LibraryService {
#Autowired
BookCategoryRepository repository;
public List<BookCategory> getAllCategories() {
return repository.findAll();
}
}
Controller:
package com.Library.controllers;
import com.Library.models.dtos.BookCategory;
import com.Library.services.LibraryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#CrossOrigin(origins = "*", allowedHeaders = "*")
#RestController
public class LibraryController{
#Autowired
LibraryService libraryService;
public List<BookCategory> getAllCategories() {
return libraryService.getAllCategories();
}
}
What could be the issue?
This bean definition is usually provided automatically by Spring Boot Auto-Configuration. The spring reference manual explains how to diagnose such issues:
The Spring Boot auto-configuration tries its best to “do the right thing”, but sometimes things fail, and it can be hard to tell why.
There is a really useful ConditionEvaluationReport available in any Spring Boot ApplicationContext. You can see it if you enable DEBUG logging output. If you use the spring-boot-actuator (see the Actuator chapter), there is also a conditions endpoint that renders the report in JSON. Use that endpoint to debug the application and see what features have been added (and which have not been added) by Spring Boot at runtime.
Many more questions can be answered by looking at the source code and the Javadoc. When reading the code, remember the following rules of thumb:
Look for classes called *AutoConfiguration and read their sources. Pay special attention to the #Conditional* annotations to find out what features they enable and when. Add --debug to the command line or a System property -Ddebug to get a log on the console of all the auto-configuration decisions that were made in your app. In a running application with actuator enabled, look at the conditions endpoint (/actuator/conditions or the JMX equivalent) for the same information.
In your case, a simple full text search finds that Hibernate is auto-configured by org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, which is declared as follows:
#AutoConfiguration(after = { DataSourceAutoConfiguration.class })
#ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })
#EnableConfigurationProperties(JpaProperties.class)
#Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {
}
As you can tell from the ConditionalOnClass annotation, this configuration is only applied if your classpath contains the classes LocalContainerEntityManagerFactoryBean from spring-orm-jpa, EntityManager from the JPA spec, and SessionImplementor from the hibernate jar.
Most likely, you are missing one of these JAR files (maven dependencies), or have the wrong version of one. The ConditionEvaluationReport should tell you which, and the precise package names to check for.

Spring boot JPA with different parent for entity and service

I have two different maven projects in first I am trying to keep two modules one for "repository and entities" and second for the services. The second project is containing only one module with the "controllers". Now I am having many problems first is "Not a managed type" for the entities. Another thing if I keep everything in one module or even in different modules with one parent project, it works flawlessly, however, I am just trying to put the different package in different project and module
The entityscan, enablejparepositries and all others are working, the debug states:
name: default
persistence provider classname: null
classloader: sun.misc.Launcher$AppClassLoader#42a57993
excludeUnlistedClasses: true
JTA datasource: null
Non JTA datasource: HikariDataSource (null)
Transaction type: RESOURCE_LOCAL
PU root URL: file:/F:/Software/MavenRepo/com/company/repo/1.0.0/repo-1.0.0.jar
Shared Cache Mode: UNSPECIFIED
Validation Mode: AUTO
Jar files URLs []
Managed classes names [
com.company.sitemap.repo.Page]
Mapping files names []
Properties []
However, At the last it states
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.company.sitemap.repo.Page
and shows error starting the application.
Can you please help me out with this?
Here is my Application class file
package com.company.sitemap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import com.company.sitemap.repo.SitemapRepoConfig;
import com.company.sitemap.service.SitemapConfig;
#SpringBootApplication
#EnableJpaRepositories(basePackageClasses = { SitemapRepoConfig.class })
#EntityScan(basePackages = {"com.nie.learn.sitemap.repo"})
#ComponentScan(basePackageClasses = { SitemapConfig.class, SitemapRepoConfig.class })
public class Sitemap extends SpringBootServletInitializer {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Sitemap.class, args);
for (String name : applicationContext.getBeanDefinitionNames()) {
System.out.println(name);
}
}
}
The entity class resides in different project and module. Let say Project-libs and module module-repo. I am trying to add this as a maven dependency.
The entity file is as follows:
package com.company.sitemap.repo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Page {
Repo config to scan repo classes.
package com.company.sitemap.repo;
import org.springframework.context.annotation.Configuration;
#Configuration
public class SitemapRepoConfig {
}
Service config to scan service classes:
package com.company.sitemap.service;
import javax.validation.constraints.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.company.sitemap.repo.PageRepository;
#Configuration
public class SitemapConfig {
#Bean
#NotNull
public SitemapService service(#NotNull PageRepository repo) {
return new SitemapService(repo);
}
}
I'll show you an example that helps us in a somewhat different case. This kind of config is used for Module1TestConf to allow separate modules testing using Spring boot slicing (#DataJpaTest, etc.) in our multi-module Gradle project to avoid loading all the context.
We just limit our module scanning to the current module + additional entities.
#SpringBootConfiguration
#EnableAutoConfiguration
#EntityScan(
basePackages = "your.other.module.package.entity",
basePackageClasses = {SomeEntity1.class, SomeEntity2.class}
)
#ComponentScan(
value = "your.current.module.package",
excludeFilters = {
#ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter),
#ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter)})
That is basically what is #SpringBootApplication is doing under the hood.
So I'm not 100% sure that it would help you. Is there a valid reason to have the projects kept as separate maven projects (use Gradle! :) )?
Anyway, you just need to make those entities scanned by Spring and become manageable...
Also try specifying entity classes directly in basePackageClasses.
You need to scan the package so that spring can create beans automatically. You are defining Page as bean but not scanning it. For scan you need to add
#ComponentScan(basePackages = { "com.nie.learn.*" })
If you have already added it than please check if Page is annotated with #Entity like below
#javax.persistence.Entity
public class Page {}
#SpringBootApplication
#EnableJpaRepositories(basePackageClasses = { com.company.sitemap.repo})
#EntityScan(basePackages = {"com.company.sitemap.repo"})
public class Sitemap extends SpringBootServletInitializer {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Sitemap.class, args);
for (String name : applicationContext.getBeanDefinitionNames()) {
System.out.println(name);
}
}
}
Try the above configuration.

How to fix "Field ... required a bean of type ... that could not be found" exception Spring Boot

I am working with spring boot tutorial from javabrains and everything was clear until putting CrudRepository inside project. Below you can find my main class:
package pl.springBootStarter.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CourseApiDataApplication
{
public static void main(String args[])
{
SpringApplication.run(CourseApiDataApplication.class,args);
}
}
Service class:
package pl.springBootStarter.app.topic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
#Service
public class TopicService
{
#Autowired
private TopicRepository topicRepository;
private List<Topic> topics = new ArrayList<>(Arrays.asList(
new Topic("spring","spring framework", "spring framework dectription"),
new Topic("sprin","spring framework", "spring framework dectription"),
new Topic("spri","spring framework", "spring framework dectription")));
public List<Topic> getAllTopics()
{
// return topics;
List<Topic> t = new ArrayList<Topic>();
topicRepository.findAll().forEach(t::add);
return t;
}
public Topic getTopic (String id)
{
return topics.stream().filter( t -> t.getId().equals(id)).findFirst().get();
}
public void addTopic(Topic topic) {
topicRepository.save(topic);
}
public void updateTopic(Topic topic, String id)
{
topics.set(topics.indexOf(topics.stream().filter(t-> t.getId().equals(id)).findFirst().get()), topic);
}
public void deleteTopic(String id)
{
topics.remove(topics.stream().filter(t -> t.getId().equals(id)).findFirst().get());
}
}
And Repository interface:
package pl.springBootStarter.app.topic;
import org.springframework.data.repository.CrudRepository;
public interface TopicRepository extends CrudRepository<Topic,String>
{
}
When I run the app there is a problem with injection of TopicRepository into topicRepository field in TopicService class. I get following error:
Error starting ApplicationContext. To display the conditions report re- run your application with 'debug' enabled.
2019-05-01 10:33:52.206 ERROR 6972 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field topicRepository in pl.springBootStarter.app.topic.TopicService required a bean of type 'pl.springBootStarter.app.topic.TopicRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
What could be the reason that Spring cannot do the autowiring?
Be sure the class is scanned by spring!
(this may help if that's the problem:
Intellij Springboot problems on startup).
Optionally you may want to annotate TopicRepository as a #Repository.
#Repository
public interface TopicRepository extends CrudRepository<Topic,String>
{
}
See a demo code here: https://github.com/lealceldeiro/repository-demo
Spring cannot inject bean because it has not been created.
You have to instruct Spring to generate implementation of declared repository interfaces by using #EnableJpaRepositories(basePackages={"pl.springBootStarter.app"}) annotation on any of your configuration classes or class annotated with #SpringBootApplication. That should fix your problem.
I got a similar message and I was missing the #Service annotation in the Service class. Simple mistake, posting in case it helps anyone else.
For anybody who was brought here by googling the generic bean error message, but who is actually trying to add a feign client to their Spring Boot application via the #FeignClient annotation on your client interface, none of the above solutions will work for you.
To fix the problem, you need to add the #EnableFeignClients annotation to your Application class, like so:
#SpringBootApplication
// ... (other pre-existing annotations) ...
#EnableFeignClients // <------- THE IMPORTANT ONE
public class Application {
I got a similar message.
the thing was my main package was com.example
and the package for other classes was com.xyz
so when I Changed the name of the package of other class to com.example.topic
i.e.
finally
The main package was com.example
and the package for the other class was com.example.topic
A simple mistake, posting in case it helps anyone else.
In my cases, the necessary configuration from org.springframework.boot.autoconfigure.jdbc. has been excluded at SpringBootApplication, causing relevant bean not added properly. Check your main application java file and see if you can find following configuration in the exclusion list
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
#SpringBootApplication(
exclude = {
DataSourceAutoConfiguration.class, // REMOVE THIS
DataSourceTransactionManagerAutoConfiguration.class, // REMOVE THIS
}
)
and remove them from exclusion list.
in service class
do:
#Autowired(required=false)

SpringBoot error : No bean named 'myController' available

I am building a basic program of "hello world" in SpringBoot
Code
MyController.java
package controllers;
import org.springframework.stereotype.Controller;
#Controller
public class MyController {
public String hello() {
System.out.println("Hello World");
return "foo";
}
}
DemoApplication.java
package di.prac;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import controllers.MyController;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(DemoApplication.class, args);
MyController m = (MyController)ctx.getBean("myController");
m.hello();
System.out.println("*******"+Arrays.asList(ctx.getBeanDefinitionNames()));
}
}
I am using eclipse and created this project from http://start.spring.io/ without any dependencies.
I learned that Spring create the bean of MyController class with name myController ,but Spring is not able to find myController bean
ERROR
Exception in thread "main"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
bean named 'myController' available at
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:686)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1210)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089)
at di.prac.DemoApplication.main(DemoApplication.java:16)
Please find and explain the error in the Project
Place your controller under sub package of di.prac like di.prac.controllers or use #ComponentScan on your controller. By default, Spring scans the current and sub packages where your main application is present. If you want to scan other packages too, then you can specify the packages in #SpringBootApplication as an argument like.
#SpringBootApplication(scanBasePackages = {"com.xyz.controllers", "com.abc.models""})
We should avoid putting the #Configuration class in the default package (i.e. by not specifying the package at all). In this case, Spring scans all the classes in all jars in a classpath. That causes errors and the application probably doesn't start.
For your controller to be available in the context of Spring, you need to define that it is managed by the Spring container. Only the #Controller annotation is not enough, it indicates only the stereotype of your bean, as well as the annotations #Repository and #Service.
In cases where the beans have these annotations and are managed by Spring, it is because their packages that the spring is scanning to search for them has been specified programmatically or per xml. In your case, you should annotate your DemoApplication class with 2 other annotations:
#Configuration - Allows access to spring context
#ComponentScan - Packages to be scanned by Spring
#Configuration
#ComponentScan (basePackages = {"controllers"})
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext ctx=SpringApplication.run(DemoApplication.class, args);
MyController m = (MyController)ctx.getBean("myController");
m.hello();
System.out.println(Arrays.asList(ctx.getBeanDefinitionNames()));
}
}
Just encountered same problem, solution is simple.You just (me also) created package "controllers" on the wrong place. It should be created not in java folder but under folder with name of your project. Simple but deadly mistake. Your code is written perfectly fine.

Categories

Resources