I have a multi module project but I am having a problem with my configuration. I have a my main method in package nl.example.hots.boot
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = {"nl.*"})
@EntityScan("nl.*")
public class HotsApplication {
public static void main(String[] args) {
SpringApplication.run(HotsApplication.class, args);
}
In the nl.example.hots.core.* package I have the class:
@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.REQUIRED)
public class MapImportService {
private MapInputModelMapper mapInputModelMapper;
private MapEntityRepository mapEntityRepository;
public void add(final MapInputModel mapInputModel) {
System.out.println(mapInputModel.getName());
mapEntityRepository.save(mapInputModelMapper.mapToEntiy(mapInputModel));
}
and:
@Component
@Mapper
public interface MapInputModelMapper {
MapInputModel mapToInputModel(final MapEntity n);
MapEntity mapToEntiy(final MapInputModel n);
}
The repository is in the package nl.example.hots.persistence.*
I get the following error when running the application:
Description:
Parameter 0 of constructor in nl.example.hots.core.dataimport.MapImportService.MapImportService required a bean of type 'nl.timonschultz.hots.core.map.mapper.MapInputModelMapper' that could not be found.
Action:
Consider defining a bean of type 'nl.example.hots.core.map.mapper.MapInputModelMapper' in your configuration.
When I remove the @EnableAutoConfiguration and @ComponentScan annotations it works. The application starts without the bean error.
In that case however my restcontroller does not work anymore:
{
"timestamp": "2018-07-18T20:48:39.414+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/maps"
}
When I remove the MapImportService class (and the bean error doesn't pop up) it works on the same url.
package nl.example.hots.api.data_import;
@RestController
@AllArgsConstructor
public class ImportController {
private static final String URL = // a url
private Reader reader;
@RequestMapping("/maps")
public String abilityStreamImport() {
reader.readStream(URL); // calls a class in nl.example.hots.core.*
return "Greetings from APP!";
}
}
I tried several different combinations and I have a different project as and example where the annotations are used together and it works right. Can somebody explain why the annotations generate the bean error when used together? And why the controller gives an error when only using @SpringBootApplication?
In my Pom.XML the boot module has a dependency on the API layer that has a dependency on the core layer that has a dependeny on the persistence layer. I'm using mapstruct and Lombok in the project.
--- edit: repository ---
@Entity(name = "MAPS")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class MapEntity extends HasId<Long> {
private String name;
@ElementCollection
private List<String> translations;
}
@Repository
public interface MapEntityRepository extends JpaRepository<MapEntity, Long> {
}
@MappedSuperclass
public abstract class HasId<T> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Setter
@Getter
private T id;
}
project structure:
hots-application;
- hots-api
- pom.xml
- nl.example.hots.api.dataimport.ImportController;
- hots-boot
- pom.xml
- nl.example.hots.boot.HotsApplication;
- hots-core
- pom.xml
- nl.example.hots.core.dataimport.mapImportService.MapImportService;
- nl.example.hots.core.map.mapper.MapInputModelMapper
- hots-persistence
- pom.xml
- nl.example.hots.persistence.common.HasId;
- nl.example.hots.persistence.map.MapEntity;
- nl.example.hots.persistence.map.MapEntityRepository;
pom.xml
Spring Boot will scan all the packages and sub packages starting with the package that the @SpringBootApplication
annotated class is in. Your class is in nl.example.hots.boot
scanning only that package. The other classes are in different, non-scanned packages.
Due to this package structure and not following the best practices you basically loose a lot of the auto configuration features (Spring Data JPA, ReST etc) and you have to resort to manually enabling/configuring that. Partially through adding additional @ComponentScan
annotation, for JPA the @EntityScan
annotations. But you would also need to add all the @EnableJpaRepository
etc. annotations as those aren't added anymore (at least not with the right packages).
The fix is fairly easy. Move your @SpringBootApplication
annotated class to the nl.example.hots
package (as stated in the best practices). Remove the annotations other then @SpringBootApplication
and simply start your application.
You're missing the @Autowired annotation on your @AllArgsConstructor, try:
@AllArgsConstructor(onConstructor = @__(@Autowired))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With