How can i fix this Exception? -> Caused by: java.lang.IllegalArgumentException: Not a managed type: - spring

i have got this Exception
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dumpController' defined in file [...\tech\backend\webapplication\com\controller\DumpController.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'dumpService' defined in file [...\tech\backend\webapplication\com\service\DumpService.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'dumpRepository' defined in tech.backend.webapplication.com.repo.DumpRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Not a managed type: class tech.backend.webapplication.com.model.Dump
...
Caused by: java.lang.IllegalArgumentException: Not a managed type: class tech.backend.webapplication.com.model.Dump
...
Process finished with exit code 1
Here are my classes:
MainClass
package tech.backend.webapplication;
#SpringBootApplication
public class WebapplicationApplication {
public static void main(String[] args) {
SpringApplication.run(WebapplicationApplication.class, args);
}
}
ModelClass:
package tech.backend.webapplication.com.model;
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#ToString
#Entity
public class Dump implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String email;
}
Repository:
package tech.backend.webapplication.com.repo;
#Repository
public interface DumpRepository extends JpaRepository<Dump, Long> {
void deleteDumpById(Long id);
Optional<Dump> findDumpById(Long id);
}
Service:
package tech.backend.webapplication.com.service;
#Service
#RequiredArgsConstructor
#Slf4j
#Transactional
public class DumpService {
private final DumpRepository dumpRepository;
public Dump addDump(Dump dump) {
dump.setName("Johannes");
dump.setEmail("Johannes#mail.com");
return dumpRepository.save(dump);
}
public List<Dump> getAllDumps() {
return dumpRepository.findAll();
}
public Dump getDumpById(Long id) {
return dumpRepository.findDumpById(id)
.orElseThrow(() -> new DumpNotFoundException("Dump by id " + id + "was not found"));
}
public Dump updateDump(Dump dump) {
return dumpRepository.save(dump);
}
public void deleteDump(Long id) {
dumpRepository.deleteDumpById(id);
}
}
Controller:
package tech.backend.webapplication.com.controller;
#RestController
#RequestMapping("/dump")
#RequiredArgsConstructor
#Slf4j
public class DumpController {
private final DumpService dumpService;
#GetMapping("/all")
public ResponseEntity<List<Dump>> getAllDumps() {
List<Dump> dumps = dumpService.getAllDumps();
return new ResponseEntity<>(dumps, HttpStatus.OK);
}
#GetMapping("/find/{id}")
public ResponseEntity<Dump> getDumpById(#PathVariable("id") Long id) {
Dump dump = dumpService.getDumpById(id);
return new ResponseEntity<>(dump, HttpStatus.OK);
}
#PostMapping("/add")
public ResponseEntity<Dump> addDump(#RequestBody Dump dump) {
Dump newDump = dumpService.addDump(dump);
return new ResponseEntity<>(newDump, HttpStatus.CREATED);
}
#PutMapping("/update")
public ResponseEntity<Dump> updateDump(#RequestBody Dump dump) {
Dump updatedDump = dumpService.updateDump(dump);
return new ResponseEntity<>(updatedDump, HttpStatus.CREATED);
}
#DeleteMapping("/delete/{id}")
public ResponseEntity<?> deleteDump(#PathVariable("id") Long id) {
dumpService.deleteDump(id);
return new ResponseEntity<>(HttpStatus.OK);
}
}
The packages are as follows:
java
tech.backend.application
com
controller
exception
model
repo
service
WebapplicationApplication (class)
ressources
Can somebody help me to fix this error?
I would appreciate that :)
Thanks
Every time I start the application, this exception is the output

Spring Boot's auto-configuration probably cannot find your entity Dump.
Add the #EntityScan annotation to your application class or a configuration class, for example:
package tech.backend.webapplication;
#SpringBootApplication
#EntityScan("tech.backend.webapplication.com.model")
public class WebapplicationApplication {
public static void main(String[] args) {
SpringApplication.run(WebapplicationApplication.class, args);
}
}

On multi-modules this issue can happen,you can do on your main class,
#SpringBootApplication
#ComponentScan(basePackages = {"tech.backend.webapplication.*"})
public class WebapplicationApplication {
public static void main(String[] args) {
SpringApplication.run(WebapplicationApplication.class, args);
}
}

Related

Create spring bean based on cmd line input

I want to create a bean with the values of string parameters provided in cmd line
#Configuration
public class SpringConfig {
#Bean
public DataProvider getDataProvider(String filePath, String mnhPath) throws Exception {
return new DataProvider(filePath, mnhPath);
}
}
#SpringBootApplication
public class SomeApplication implements CommandLineRunner {
#Autowired
private BeanFactory beanFactory;
public static void main(String[] args) {
SpringApplication.run(SomeApplication .class, args);
}
#Override
public void run(final String... args) throws Exception {
final CommandLineArgs arguments = new CommandLineArgs();
CmdLineParser parser = new CmdLineParser(arguments);
parser.parseArgument(args);
DataProvider dataProvider = beanFactory.getBean(DataProvider.class, arguments.one(), arguments.two());
dataProvider.doSomeOperation();
}
}
But I am getting an error
Description:
Parameter 0 of constructor in com.tomtom.display.height.HeightsDataProvider required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
How should I correctly configure the bean?
It does not seem to work if you try to create a bean of the format, and attempt at retrieving it.
#Bean
public Bean myBean(String xyz){
return new Bean(xyz);
}
You could bypass this limitation by doing the following:
#Getter
#Setter
#NoArgsConstructor
public class MyBeanExample{
private String hello;
private String world;
}
#SpringBootApplication
public class DemoApplication {
#Bean
public MyBeanExample myBeanExample(){
return new MyBeanExample();
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
MyBeanExample beanWithArgs = ctx.getBean(MyBeanExample.class);
beanWithArgs.setHello(args[0]);
beanWithArgs.setWorld(args[1]);
System.out.println(beanWithArgs.getHello());
System.out.println(beanWithArgs.getWorld());
}
}
This would retrieve your #Bean myBeanExample() and then you use setters to set the parameters you need.

Couldn't find PersistentEntity for type class when using #EnableMongoAuditing

I am getting "Couldn't find PersistentEntity for type class" error when I am using #EnableMongoAuditing features along with MongoRepository.
This happens when I save a document when collection isn't already present in database.
I tried whatever is mentioned in:
https://github.com/spring-projects/spring-boot/issues/12023
https://jira.spring.io/browse/DATAMONGO-1999
Spring boot mongodb auditing error
but nothing is working.
Mentioned things are:
Extend MongoConfig by AbstractMongoConfiguration and override all methods.
Here is my code which reproduced the same error:
MongoConfig class
#Configuration
public class MongoConfig extends AbstractMongoConfiguration {
#Value("${spring.data.mongodb.host}")
private String mongoHost;
#Value("${spring.data.mongodb.port}")
private String mongoPort;
#Value("${spring.data.mongodb.database}")
private String mongoDB;
#Override
public MongoDbFactory mongoDbFactory() {
return new SimpleMongoDbFactory(new MongoClient(mongoHost + ":" + mongoPort), mongoDB);
}
#Override
public MongoClient mongoClient() {
return new MongoClient(mongoHost, Integer.parseInt(mongoPort));
}
#Override
public MongoTemplate mongoTemplate() {
return new MongoTemplate(mongoDbFactory());
}
#Override
public MappingMongoConverter mappingMongoConverter() {
return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}
#Override
protected String getDatabaseName() {
return mongoDB;
}
}
Person Collection class
#Document
public class Person {
#Id
private String id;
private String name;
#CreatedDate
private LocalDateTime createdAt;
#LastModifiedDate
private LocalDateTime lastModified;
// Getter Setters Constructors omitted for brevity
}
Main Application class
#EnableMongoAuditing
#EnableMongoRepositories ({"com.example.*", "org.apache.*"})
#SpringBootApplication
#ComponentScan({"com.example.*", "org.apache.*"})
public class DemoApplication implements CommandLineRunner {
#Autowired
PersonRepository personRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
Person p1 = new Person("1", "prakhar");
personRepository.save(p1);
}
}
Expected Result is Person entity should be saved in database.
Actual Result is "Couldn't find PersistentEntity for type class Person" error
Looks like you ran into https://github.com/spring-projects/spring-boot/issues/12023
Extending AbstractMongoConfiguration will switch off Spring Boot's auto-configuration of various Mongo components and also customises the base packages that are used to scan for mappings. I would recommend that you don't use it in Spring Boot.
Update
I managed to get the example running with the configuration as simple as
#Configuration
public class MongoConfig {
#Value("${spring.data.mongodb.host}")
private String mongoHost;
#Value("${spring.data.mongodb.port}")
private String mongoPort;
#Value("${spring.data.mongodb.database}")
private String mongoDB;
#Bean
public MongoDbFactory mongoDbFactory() {
return new SimpleMongoDbFactory(new MongoClient(mongoHost + ":" + mongoPort), mongoDB);
}
#Bean
public MongoClient mongoClient() {
return new MongoClient(mongoHost, Integer.parseInt(mongoPort));
}
}
and the app class
#EnableMongoAuditing
#SpringBootApplication
public class DemoApplication implements CommandLineRunner {
#Autowired
PersonRepository personRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
Thread.sleep(2000);
Person p1 = new Person("1", "prakhar");
personRepository.save(p1);
}
}
Notice that I followed my own advice and did't inherit from AbstractMongoConfiguration
Explanation
The problem lies in the initialization of
#Bean
public MappingMongoConverter mappingMongoConverter() {
return new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory()), new MongoMappingContext());
}
You simply call MongoMappingContext constructor, without calling setInitialEntitySet. Compare that with MongoDataConfiguration auto-configuration class.
#Bean
#ConditionalOnMissingBean
public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions)
throws ClassNotFoundException {
MongoMappingContext context = new MongoMappingContext();
context.setInitialEntitySet(new EntityScanner(this.applicationContext)
.scan(Document.class, Persistent.class));
Class<?> strategyClass = this.properties.getFieldNamingStrategy();
if (strategyClass != null) {
context.setFieldNamingStrategy(
(FieldNamingStrategy) BeanUtils.instantiateClass(strategyClass));
}
context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
return context;
}
Even worse, you don't register MongoMappingContext as a managed bean.
Due to this fact, auto-configuration class is still created. This leads to a race condition, I tried to run the original code and could easily reproduce the error, but with a breakpoint in AbstractMappingContext.addPersistentEntity the test always passed.
For me I resolved this issue by adding following method in MongoConfig if your class extends from AbstractMongoConfiguration
#Override
protected String getMappingBasePackage() {
return "com.companyName.modulename"
}
If MongoConfig extends from MongoConfigurationSupport then add below method
#Override
protected Collection<String> getMappingBasePackages() {
return Arrays.asList("com.companyName.module1","com.companyName.module2");
}
Note that in later case I can specify multiple package names as base packages.

Spring boot - autowire fails

I'm trying to fetch some properties from application.properties file ad my code is the following:
Main Application class:
package it.mysite;
#SpringBootApplication
#EnableTransactionManagement
public class MailSenderApplication {
public static void main(String[] args){
ConfigurableApplicationContext context = SpringApplication.run(MailSenderApplication.class, args);
System.out.println("*****");
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println("*****");
new MySendService().sendReport();
}
}
My service class:
package it.mysite.service;
#Service
public class MySendService {
#Value("${mail.fc.to}")
private String[] to;
#Value("${mail.fc.subject}")
private String subject;
#Autowired ReportService reportEmailService;
#Autowired MailProperties mailProperties;
public void sendReport(){
if(mailProperties.getTo().length > 0) {
}
}
Class where I fetch the properties:
package it.mysite.properties;
#Component
#ConfigurationProperties("mail.fc")
public class MailProperties {
private String[] to;
public String[] getTo(){
return to;
}
}
Config file:
# Email config
mail.fc.to=my#mail.com
mail.fc.subject=My subject
All of the #Autowired properties are null, and also the #Value properties (I tried to get them in that way also). When I print my context I can see these classes in the bean list, and for what I know my packages hierarchy is correct, so what can be the problem?
EDIT
Ok, I got the suggestion from the duplicate question and I changed my main class code as follows:
Main Application class:
package it.mysite;
#SpringBootApplication
#EnableTransactionManagement
public class MailSenderApplication {
#Autowired MySendService mySendService;
public static void main(String[] args){
ConfigurableApplicationContext context = SpringApplication.run(MailSenderApplication.class, args);
System.out.println("*****");
for (String name : context.getBeanDefinitionNames()) {
System.out.println(name);
}
System.out.println("*****");
new MailSenderApplication().boot();
}
private void boot(){
mySendService.sendReport();
}
}
But I got the same error. Wasn't that the suggestion?

Junit test for saving data with JPA

Am trying to make a junit test to save data with JPA. Below is my entity class
#Entity
#Table(name="book")
public class test {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="BOOK_REF_ID",nullable=false)
private int bookRefId;
#Column(name="BOOK_CODE",nullable=false)
private String bookCode;
#Column(name="BOOK_NAME",nullable=false)
private String bookDescription;
public int getBookRefId() {
return bookRefId;
}
public void setBookRefId(int bookRefId) {
this.bookRefId = bookRefId;
}
public String getBookCode() {
return bookCode;
}
public void setBookCode(String bookCode) {
this.bookCode = bookCode;
}
public String getBookDescription() {
return bookDescription;
}
public void setBookDescription(String bookDescription) {
this.bookDescription = bookDescription;
}
}
Service class is
public interface BookService()
{
public Book create(Book book);
}
Repository class is
public interface BookRepository extends
JpaRepository<Book,Integer>
{ }
Service Implementation class is
public BookServiceImpli implements BookService()
{
#Resource
BookRepository repository;
#Override
public Book create(Book book) {
// TODO Auto-generated method stub
return repository.save(book);
}
}
Now my test class is
#RunWith(SpringRunner.class)
#DataJpaTest
#SpringBootTest(classes= {JPAConfig.class})
#AutoConfigureTestDatabase(replace=Replace.NONE)
#TestPropertySource(
locations = "classpath:application.properties")
public class TestBook {
#Autowired
private BookService bookService ;
#Test
public void test() {
Book book = new Book();
book.setBookCode("abc");
book.setBookDescription("safd");
bookService.create(book);
}
Application properties contains password and database details and JPAConfig contain JPA configuration details such as entity scan database details. When am trying to run the test case am getting an error like
A component required a bean of type
'com.repository.sample.BookRepository' that could not be found.
I don't have main method in it.Am new to unit testing please anyone help me to solve the issue.

Spring Bean Factory Configuration passing input parameter

I'm trying to create a BeanFactory called TaskBeanFactory that I can Autowire into another prototype class that's running on a thread. I want a different instance of a bean returned by the Factory based on a taskName that i want to pass into it but when i start the application i get a null pointer exception because the taskName is null. I had a look at this article but i'm confused about how I should configure the Factory and then pass in the taskName.
The Factory:
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.stereotype.Component;
#Data
#Component
#NoArgsConstructor
public class TaskBeanFactory extends AbstractFactoryBean<GenericTask>{
private TaskNameEnum taskName;
public TaskBeanFactory(TaskNameEnum taskName) {
setSingleton(false);
}
#Override
public Class<?> getObjectType() {
return GenericTask.class;
}
#Override
protected GenericTask createInstance() throws Exception {
switch (taskName) {
case FILE_OPERATION:
return new FileTask();
case DATA_OPERATION:
return new DataTask();
default:
return new GenericTask();
}
}
}
The classes used by the Factory:
#Data
public class GenericTask {
private String idTask;
public void executeTask(Work work) {};
}
#Component
#Scope(value="prototype")
public class FileTask extends GenericTask {
#Override
public void executeTask(Work work) {
//some processing
}
}
#Component
#Scope(value="prototype")
public class DataTask extends GenericTask {
#Override
public void executeTask(Work work) {
//some processing
}
}
and the thread that's calling the Factory:
#Slf4j
#Data
#Scope("prototype")
#Component
public class WorkerThread implements Runnable {
#Autowired
private TaskBeanFactory taskBeanFactory;
#Autowired
private DataService dataService;
#Override
public void run() {
//iterate a Map of taskIds from the dataService
taskBeanFactory.setTaskName(TaskNameEnum.valueOf(taskEntry.getKey()));
GenericTask genericTask = taskBeanFactory.getObject();
//expecting genericTask to be of Type FileTask if called with one Key
//or of Type DataTask if called with another
}
}
}

Resources