Spring Boot @Mapper Bean creation issue : Application Failed to start. Error : Consider defining a bean of Type

huangapple go评论92阅读模式
英文:

Spring Boot @Mapper Bean creation issue : Application Failed to start. Error : Consider defining a bean of Type

问题

以下是翻译好的部分:

错误信息

***************************
应用程序启动失败
***************************

**描述**:

com.example.accessingdatamysql.rest.MainController中的字段userService需要一个类型为'com.example.accessingdatamysql.service.UserService'的bean,但找不到该bean。

注入点具有以下注解:
- @org.springframework.beans.factory.annotation.Autowired(required=true)

操作:

考虑在您的配置中定义一个类型为'com.example.accessingdatamysql.service.UserService'的bean。

问题出在MainController中导入了"UserService":

package com.example.accessingdatamysql.rest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.example.accessingdatamysql.model.dto.UserDto;
import com.example.accessingdatamysql.service.UserService;

@RestController
public class MainController {
  @Autowired 
  private UserService userService;

  @Transactional
  @PostMapping(path="/demo/add")
  public @ResponseBody String addNewUser (@RequestParam String name, @RequestParam String email, @RequestParam String surname) 
  {
    UserDto n = new UserDto();
    n.setName(name);
    n.setSurname(surname);
    n.setEmail(email);
    userService.create(n);
    return "Saved";
  }

  @GetMapping("/demo/first")
  public UserDto one(@RequestParam String name) {
    System.out.print(name);
    return userService.findFirstByName(name); 
  }
}

可能是一个微不足道的问题,但我无法绕过这个问题,下面我插入"UserService"和MainStart。

UserService.java

package com.example.accessingdatamysql.service;

import com.example.accessingdatamysql.model.dto.UserDto;

public interface UserService {
    UserDto findFirstByName(String name);
    void create(UserDto user);
}

更新
我插入了UserServiceImpl、新的main和Mapper,出现了新的错误。

UserServiceImpl.java

package com.example.accessingdatamysql.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.accessingdatamysql.model.dto.UserDto;
import com.example.accessingdatamysql.model.entity.UserEntity;
import com.example.accessingdatamysql.model.repo.UserRepository;
import com.example.accessingdatamysql.util.UserMapper;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    UserMapper mapper;

    @Override
    public UserDto findFirstByName(String name) {
        UserEntity entity = userRepository.findFirstByName(name);
        return mapper.toDtoMapper(entity);
    }

    @Override
    public void create(UserDto user) {
        UserEntity entity = mapper.toEntityMapper(user);
        userRepository.create(entity);
    }
}

AccessingDataMysqlApplication.java

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication(scanBasePackages = { "com.example.accessingdatamysql", "com.example.accessingdatamysql.util" })
public class AccessingDataMysqlApplication {
    public static void main(String[] args) {
        SpringApplication.run(AccessingDataMysqlApplication.class, args);
    }
}

UserMapper.java

package com.example.accessingdatamysql.util;

import org.mapstruct.Mapper;

import com.example.accessingdatamysql.model.dto.UserDto;
import com.example.accessingdatamysql.model.entity.UserEntity;

@Mapper(componentModel = "spring")
public interface UserMapper {
    UserEntity toEntityMapper(UserDto user);
    UserDto toDtoMapper(UserEntity userEntity);
}

新错误

***************************
应用程序启动失败
***************************

描述:

com.example.accessingdatamysql.service.UserServiceImpl中的字段mapper需要一个类型为'com.example.accessingdatamysql.util.UserMapper'的bean,但找不到该bean。

注入点具有以下注解:
- @org.springframework.beans.factory.annotation.Autowired(required=true)

操作:

考虑在您的配置中定义一个类型为'com.example.accessingdatamysql.util.UserMapper'的bean。

POM.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>accessingdatamysql</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>project</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.3.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
英文:

I am new to spring, when i try to do the mvn clean install of my project this problem appears:

Error

***************************
APPLICATION FAILED TO START
***************************
**Description**:
Field userService in com.example.accessingdatamysql.rest.MainController required a bean of type &#39;com.example.accessingdatamysql.service.UserService&#39; 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 of type &#39;com.example.accessingdatamysql.service.UserService&#39; in your configuration.

The problem is that in the MainController there is the import of "UserService":

package com.example.accessingdatamysql.rest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.accessingdatamysql.model.dto.UserDto;
import com.example.accessingdatamysql.service.UserService;
@RestController
public class MainController {
@Autowired 
private UserService userService;
@Transactional
@PostMapping(path=&quot;/demo/add&quot;)
public @ResponseBody String addNewUser (@RequestParam String name
, @RequestParam String email,@RequestParam String surname) 
{
UserDto n = new UserDto();
n.setName(name);
n.setSurname(surname);
n.setEmail(email);
userService.create(n);
return &quot;Saved&quot;;
}
@GetMapping(&quot;/demo/first&quot;)
public UserDto one(@RequestParam String name) {
System.out.print(name);
return userService.findFirstByName(name); 
}
}

It is probably a trivial thing but I can not bypass the problem, below I insert "UserService" and the MainStart

UserService.java

package com.example.accessingdatamysql.service;
import com.example.accessingdatamysql.model.dto.UserDto;
public interface UserService {
UserDto findFirstByName(String name);
void create(UserDto user);
}

UPDATE :
I insert the UserServiceImpl and the new main and Mapper, with the new error.

UserServiceImpl.java

package com.example.accessingdatamysql.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.dto.UserDto;
import com.example.accessingdatamysql.model.entity.UserEntity;
import com.example.accessingdatamysql.model.repo.UserRepository;
import com.example.accessingdatamysql.util.UserMapper;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserRepository userRepository;
@Autowired
UserMapper mapper;
@Override
public UserDto findFirstByName(String name) {
UserEntity entity = userRepository.findFirstByName(name);
return mapper.toDtoMapper(entity);
}
@Override
public void create(UserDto user) {
UserEntity entity = mapper.toEntityMapper(user);
userRepository.create(entity);
}
}

AccessingDataMysqlApplication.java

package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication(scanBasePackages = { &quot;com.example.accessingdatamysql&quot;,
&quot;com.example.accessingdatamysql.util&quot;})
public class AccessingDataMysqlApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingDataMysqlApplication.class, args);
}
}

UserMapper.java

package com.example.accessingdatamysql.util;
import org.mapstruct.Mapper;
import com.example.accessingdatamysql.model.dto.UserDto;
import com.example.accessingdatamysql.model.entity.UserEntity;
@Mapper (componentModel = &quot;spring&quot;)
public interface UserMapper {
UserEntity toEntityMapper (UserDto user);
UserDto toDtoMapper (UserEntity userEntity);
}

New Error:

***************************
APPLICATION FAILED TO START
***************************
Description:
Field mapper in com.example.accessingdatamysql.service.UserServiceImpl required a bean of type &#39;com.example.accessingdatamysql.util.UserMapper&#39; 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 of type &#39;com.example.accessingdatamysql.util.UserMapper&#39; in your configuration.

POM

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;parent&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
&lt;version&gt;2.3.4.RELEASE&lt;/version&gt;
&lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
&lt;/parent&gt;
&lt;groupId&gt;com.example&lt;/groupId&gt;
&lt;artifactId&gt;accessingdatamysql&lt;/artifactId&gt;
&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
&lt;name&gt;project&lt;/name&gt;
&lt;description&gt;Demo project for Spring Boot&lt;/description&gt;
&lt;properties&gt;
&lt;java.version&gt;1.8&lt;/java.version&gt;
&lt;/properties&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct&lt;/artifactId&gt;
&lt;version&gt;1.3.1.Final&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;mysql&lt;/groupId&gt;
&lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;exclusions&gt;
&lt;exclusion&gt;
&lt;groupId&gt;org.junit.vintage&lt;/groupId&gt;
&lt;artifactId&gt;junit-vintage-engine&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;/project&gt;

答案1

得分: 4

将您的UserService类的实现(类似于UserServiceImpl.java)使用@Service@Component进行注解。同时确保该类位于一个子包中。

您的主类包是:com.example.accessingdatamysql。您的UserService类和所有其他类都应该放在一个包中,例如:com.example.accessingdatamysql.xxxxxx。请确保遵循这个策略。

此外,移除主类上的不必要的注解。@SpringBootApplication注解等效于以下三个注解的组合:

  1. @Configuration
  2. @EnableAutoConfiguration
  3. 带有属性的@ComponentScan

以下内容足够了:

@SpringBootApplication(scanBasePackages = "com.example.accessingdatamysql")

在进行Bean注入时,不要在任何Bean注入之间留有空隙。这不会造成任何问题。但是您的代码应该被适当地组织和缩进。

还需要将以下内容替换为:

@Autowired          
private UserService userService;

更新1

在修复Spring Boot配置后,执行mvn clean install

更新2

您的Mapper Bean没有完全符合Spring Bean的要求。您需要使用以下插件编译项目(参见我使用的第二个插件)。

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<configuration>
				<source>1.8</source>
				<target>1.8</target>
				<annotationProcessorPaths>
					<path>
						<groupId>org.mapstruct</groupId>
						<artifactId>mapstruct-processor</artifactId>
						<version>1.3.1.Final</version>
					</path>
				</annotationProcessorPaths>
				<compilerArgs>
					<compilerArg>
						-Amapstruct.defaultComponentModel=spring
					</compilerArg>
				</compilerArgs>
			</configuration>
		</plugin>
	</plugins>
</build>

然后,您需要将您的UserDto.java修复如下(更改时间戳变量的类型,否则Mapper会失败):

import java.sql.Timestamp;

private Timestamp timestamp;

public Timestamp getTimestamp() {
    return timestamp;
}

public void setTimestamp(Timestamp timestamp) {
    this.timestamp = timestamp;
}

您的主类应该只有以下内容:@SpringBootApplication(scanBasePackages = "com.example.accessingdatamysql"),没有其他注解。

然后保存您的项目。接着运行:mvn clean install -X

确保您的包结构如下所示:

(包结构的图片)

以及您的类按照以下方式排列:

(类在包中的图片)

英文:

Annotate your UserService class implementation [like UserServiceImpl.java] with @Service or @Component. Also make sure this class is located in a sub-package.

This is your main class package : com.example.accessingdatamysql
Your UserService class and all other classes should be kept in a package like : com.example.accessingdatamysql.xxxxxx. Ensure this strategy is followed.

Plus remove the unnecessary annotations on your main class. The @SpringBootApplication annotation is equivalent to using the below 3 :
:

  1. @Configuration,
  2. @EnableAutoConfiguration and
  3. @ComponentScan with attributes.

This will be enough :

@SpringBootApplication (scanBasePackages = &quot;com.example.accessingdatamysql&quot;)

And do not keep a gap when you autowire any bean injection. This does not cause any harm. But your code should be properly organized and indentation done.

Also replace below :

 @Autowired 
private UserService userService;

With this :

 @Autowired          
private UserService userService;

UPDATE-1

Do a maven clean install after you fix your spring boot configurations.

mvn clean install

UPDATE-2

Your bean for Mapper does not fully qualify for a spring bean. You need to compile your project with the below plugin (see the 2nd plugin I have used).

&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
&lt;/plugin&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
&lt;configuration&gt;
&lt;source&gt;1.8&lt;/source&gt;
&lt;target&gt;1.8&lt;/target&gt;
&lt;annotationProcessorPaths&gt;
&lt;path&gt;
&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;
&lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;
&lt;version&gt;1.3.1.Final&lt;/version&gt;
&lt;/path&gt;
&lt;/annotationProcessorPaths&gt;
&lt;compilerArgs&gt;
&lt;compilerArg&gt;
-Amapstruct.defaultComponentModel=spring
&lt;/compilerArg&gt;
&lt;/compilerArgs&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;

Then you need to fix your UserDto.java as below (change the type of timestamp variable else Mapper will fail):

import java.sql.Timestamp;
private Timestamp timestamp;
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}

Your main class should only have this : @SpringBootApplication (scanBasePackages = &quot;com.example.accessingdatamysql&quot;) and no other annotation.

Then save your project. And Then run : mvn clean install -X

Make your package structure like this :

Spring Boot @Mapper Bean creation issue : Application Failed to start. Error : Consider defining a bean of Type

And your classes arranged in the below way :

Spring Boot @Mapper Bean creation issue : Application Failed to start. Error : Consider defining a bean of Type

答案2

得分: 0

你需要定义一个Bean,让Spring可以使用它们,例如在这种情况下使用依赖注入(Dependency Injection)的@Autowired

有多种方法来定义这些Beans,但在你的情况下,可以在服务类上使用@Service注解,这样Spring在初始化过程中就能找到它。

而且你不需要声明@ComponentScan注解,@SpringbootApplication会处理所有事情。

正如@Som所说,你需要实现你的UserService类,因为它是一个接口,目前还没有实现的类。

尝试移除@ComponentScan注解,并按照以下方式实现UserService接口:

@Service
public class UserServiceImpl implements UserService{
    // 其余的代码
}
英文:

You need to define a bean to let the Spring use them such as DI(Dependency Injection) @Autowired in this case.

There are various ways to define the beans but in your case using @Service annotation on the service class so that Spring can find it during the initialization.

And you don't need to declare @ComponentScan annotation the @SpringbootApplication will handle everything.

As @Som said, you need to implement your Userservice class since it is interface and there is no implemented class yet.

Try to remove @ComponentScan annotation and implement UserService interface as follow

@Service
public class UserServiceImpl implements UserService{
    // the rest of the code
}

huangapple
  • 本文由 发表于 2020年10月3日 18:21:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/64183146.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定