Spring boot #Autowired can't initialise class - java

I have following class as:-
#SpringBootApplication
#ComponentScan("com.ma.demospringboot")
public class DemoSpringBootApp {
public static void main(String[] args) {
SpringApplication.run(DemoSpringBootApp.class, args);
}
}
I have following class as:-
#Service
public class TopicService {
// if I comment out following autowired, then it is ok.
#Autowired
private TopicRepository topicRepository;
}
I have following interface as:-
public interface TopicRepository extends CrudRepository<Topic, String> {
}
I have following class as:-
#Entity
public class Topic {
#Id
private String id;
private String name;
private String description;
public Topic() {
}
}
I got following error when try to execute:-
APPLICATION FAILED TO START
Description:
Field topicRepository in com.ma.demospringboot.service.TopicService
required a bean of type
'com.ma.demospringboot.repository.TopicRepository' that could not be
found.
Action:
Consider defining a bean of type
'com.ma.demospringboot.repository.TopicRepository' in your
configuration.

Spring container is not finding your repository classes during the scan, add #EnableJpaRepositories to explicitly specify the packages of where your repository classes exist, as shown below:
#SpringBootApplication
#ComponentScan("com.ma.demospringboot")
#EnableJpaRepositories("com.ma.demospringboot.repository")
#EntityScan(basePackages = "com.ma.demospringboot.domain")
public class DemoSpringBootApp {
//your current code here
}
UPDATE1:
Not a managed type: class com.ma.demospringboot.domain.Topic
Now, your Topic entity class not found, so you need to #EntityScan(basePackages = "com.ma.demospringboot.domain") to scan the entity classes (as show above).
UPDATE2:
I did exactly as you suggested, but NOT working
There is a problem with the way that you are packaging the classes, double check on that, also ensure that the latest classes have been compiled/built & used by the server.

Your Spring container is unable to find and identify your JPA repositories.
Add #EnableJpaRepositories("com.ma.demospringboot.repository") on your DemoSpringBootApp class
#SpringBootApplication
#ComponentScan("com.ma.demospringboot")
#EnableJpaRepositories("com.ma.demospringboot.repository")
public class DemoSpringBootApp {
public static void main(String[] args) {
SpringApplication.run(DemoSpringBootApp.class, args);
}
}

add following code in your ApplicationContext.xml
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

Related

Multiple instances of a bean of one class filled with values from application.properties

I intend to write some HealtCheckContributors for a Spring Boot application using spring-boot-actuator. Hence, I implemented two of them. they are intended for checking the health of different apps, of course, but have a nearly identical structure, except the configuration properties, ...
SonarQube complains about that and I wonder if it is possible to have a single health check class but instantiated as many times as defined in application.properties.
An example:
application.properties:
# actuator
app1.management.baseUrl=http://localhost:10000
app1.management.name=app1HealthCheckContributor
app2.management.basUrl=http://localhost:10001
app2.management.name=app2HealthCheckContributor
HealthCheckContributor for app1:
#Slf4j
#Component("xxx")
public class App1HealthCheckContributor extends AbstractHealthIndicator {
private final App1Properties app1Properties;
public App1HealthCheckContributor(final App1Properties app1Properties) {
this.app1Properties = app1Properties;
}
#Override
protected void doHealthCheck(Health.Builder builder) {...}
}
...and this code for each HealthCheckContributor only distinct in its appXProperties.
Isn't it possible to have some kind of base class like:
#Slf4j
#Component()
public class MyHealthCheckContributor extends AbstractHealthIndicator {
private final MyProperties myProperties;
public MyHealthCheckContributor(final MyProperties myProperties) {
this.myProperties = myProperties;
}
#Override
protected void doHealthCheck(Health.Builder builder) {...}
}
and let Spring Boot take care of instantiating two HealthCheckContributors (in our case App1HealthCheckContributor and App2HealthCheckContributor)?
This would eliminate code duplication.
An example of the properties class file:
#Slf4j
#Data
#ConfigurationProperties(prefix = "app1.management")
public class App1Properties {
private String baseUrl;
private String ...;
}
How can I achieve this and how must an application.properties file looks like to achieve what I intend to do?
The final question: How to test multiple instance creation of a bean of one class filled with values from application.properties?
Assuming the code in doHealthCheck is exactly the same for all apps to be checked you could do the following.
You would start by creating a single health check class:
#Slf4j
public class AppHealthCheckContributor extends AbstractHealthIndicator {
private final AppProperties appProperties;
public App1HealthCheckContributor(final AppProperties appProperties) {
this.appProperties = appProperties;
}
#Override
protected void doHealthCheck(Health.Builder builder) {...}
}
And the properties model as follows:
#Slf4j
#Data
public class AppProperties {
private String baseUrl;
private String name;
}
This means that the configuration would be something like the following (in application.yml):
health-check:
apps:
- baseUrl: http://localhost:10000
name: app1
- baseUrl: http://localhost:10001
name: app2
Finally, you would need to create a bean for each app and register them in the application context:
#Slf4j
#Data
#Configuration
#ConfigurationProperties(prefix = "health-check")
public class AllAppPropertiesConfiguration {
private List<AppProperties> apps;
#Autowired
private GenericApplicationContext applicationContext;
#PostConstruct
fun init() {
for (AppProperties app : apps) {
applicationContext.registerBean(app.getName(), AppHealthCheckContributor.class, app);
}
}
}

Spring Boot Application not registering #Repository

I'm creating a simple SpringBoot application with spring-data-jpa for learning purposes.
My problem is when I try to #Autowire a #Repository the application always fails to start with the error:
APPLICATION FAILED TO START
***************************
Description:
Field pedidoRepository in com.pedidos.services.PedidoService required a bean of type 'com.pedidos.repositories.PedidoRepository' 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 'com.pedidos.repositories.PedidoRepository' in your configuration.
All the answers that i have found so far tells me to do something that is already done in my application. I'm probably missing something and I can't find out what it is.
This is how my application is now (imports are omitted):
Application:
package com.pedidos;
#SpringBootApplication
public class PedidosApplication {
public static void main(String[] args) {
SpringApplication.run(PedidosApplication.class, args);
}
}
Repository:
package com.pedidos.repositories;
#Repository
public abstract class PedidoRepository implements JpaRepository<Pedido, UUID> {
}
Service:
package com.pedidos.services;
#Service
public class PedidoService {
#Autowired
private PedidoRepository pedidoRepository;
public Optional<Pedido> findById(UUID id){
return pedidoRepository.findById(id);
}
public Pedido save(Pedido pedido){
return pedidoRepository.save(pedido);
}
}
Controller:
package com.pedidos.controllers;
#Controller("/pedido")
public class PedidoController {
#Autowired
private PedidoService pedidoService;
#GetMapping("/{id}")
public Pedido get(#PathVariable(name = "id") UUID id){
return pedidoService.findById(id).get();
}
}
Here is my Project structure
If do not inject the repository the application runs fine.
The entire code is in this GitHub repo: https://github.com/brunomokan/pedidos
Like what ILya Cyclone say. A Spring-Data Repository should be an interface which get a proxy at runtime. Something like this. Its fine if you extend from another interface.

Spring Crud Repository - Unsatisfied dependency expressed - Cant inject model

i seem to be unable to get Spring to recognize the native CrudRepository and use it, because spring isn not able to inject / use the actual class that my generic CrudRepository needs to implement when i put it in a different package than the one with the main method.
My Project structure is pretty straight forward.
Leaving the structure like this works just fine!
I want however Author to be inside the model package, like this:
However Spring always throws the error:
Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'authorRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorRepository' defined in service.AuthorRepository defined in #EnableJpaRepositories declared on DemoApplication: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class model.Author
I definately dont want to use a configuration through an application.properties.xml file. I want it to be programmatically configured within java code.
The Author.java :
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "authors")
public class Author {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(nullable = false)
private String name;
}
The AuthorRepository that implements the CrudRepository:
#Repository
public interface AuthorRepository extends CrudRepository<Author, Integer> {
}
If it is of any importance here is the Config class where i define my DataSource. The #Bean with Author seems not important, since it works without it too when i leave the Author inside the com.example.demo package.
#Configuration
public class Config {
#Bean
public DataSource dataSource(){
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url("jdbc:mysql://localhost:3306/sks");
dataSourceBuilder.username("sks");
dataSourceBuilder.password("technikum1");
return dataSourceBuilder.build();
}
#Bean
public Author author(){
return new Author();
}
}
And finally my Main method:
#SpringBootApplication
#ComponentScan(basePackages = {"config"})
#EnableJpaRepositories(basePackages = {"service"})
public class DemoApplication implements CommandLineRunner {
#Autowired
private AuthorRepository authorRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
#Transactional
public void run(String... args) throws Exception {
Iterable<Author> authors = authorRepository.findAll();
System.out.println(authors);
}
}
I tried annotating the AuthorRepository with a #ComponentScan(basePackages = {"model"}) and annotated the Author.java with #Component because i thought it might not recognize it as bean or something if i put it in another package ( which would be strange anyway since i dont need the component annotation when i leave it in the main package) but nothing worked so far.
Generally struggling hard with project structure and Spring....
Also i have tried to change the #ComponentScan(basePackages = {"config"}) in DemoApplication to #ComponentScan(basePackages = {"config","model"}).
Nothing worked so far !
I need some help ...

Springboot - #ConfigurationProperties not populating the class fields

I know similar questions have been asked many times with different variations. I have tried to learn from them and from the available tutorials and try to get it working but I think I am missing something that I am not able to figure out.
I want to load a configuration from the external yaml file admin-config.yml, and not the default application.yml in my case.
This is what I have done so far.
Annotated the Application file with #EnableConfigurationProperties
#SpringBootApplication
#EnableConfigurationProperties
public class MyServer {
public static void main(String[] args) {
SpringApplication.run(MyServer.class, args);
}
}
The AdminConfig component class:
#Component
#PropertySource("classpath:admin-config.yml")
#ConfigurationProperties(prefix = "admin-config")
public class AdminConfig {
private List<PrimeModerator> primeModerators;
#PostConstruct
public void init() {
System.out.println(primeModerators); // this is null
}
public void setPrimeModerators(List<PrimeModerator> primeModerators) {
this.primeModerators = primeModerators;
}
public List<PrimeModerator> getPrimeModerators() {
return primeModerators;
}
}
The PrimeModerator class
#Data
public class PrimeModerator implements Serializable {
private long id;
private String name;
private List<String> roles;
private String details;
private Date created;
}
The admin-config.yml.
admin-config:
primeModerators:
- !!com.mydomain.model.PrimeModerator
id: 1
name: Pawan
roles: [super-admin]
- !!com.mydomain.model.PrimeModerator
id: 2
name: Prashant
roles: [admin, moderator]
I have created a unit test case which always fails (which should not).
#SpringBootTest
#RunWith(SpringRunner.class)
public class AdminConfigTest {
#Autowired
private AdminConfig adminConfig;
#Test
public void testAdminConfig() {
assertNotNull(adminConfig.getPrimeModerators()); // this fails
}
}
I am not sure what I am missing here. Using springboot version 2.2.1.RELEASE with jdk8.
Thanks for your answers in advance!
from this documentation :
Baeldung - Spring
It says :
"The Hibernate Validation framework uses standard Java bean getters and setters, so it's important that we declare getters and setters for each of the properties."
Could you please test by adding getters/settest in PrimeModerator ?
Did you try with a single simple String value before you nested array ?
Good luck...
A github sample on Baeldung in the bottom of page

Spring Boot defining bean in configuration problem

I'm working on a project on my sparetime, on this project I have been asked to work with Spring Boot. I'm not familiar with Spring Boot from before, and I have tried searching here on stackoverflow and Google, but I can't seem to understand how the different solutions for my problem works.
First of all, this is my error message:
Parameter 0 of constructor in com.project.example.controller.VerverController required a bean of type 'com.project.example.dao.VerverDao' that could not be found.
Action:
Consider defining a bean of type 'com.project.example.dao.VerverDao' in your configuration.
After some reading, I understood that this could be because of Spring Boot don't scan this class / interface. So I tried to add ComponentScan, with no luck.
I tried to convert VerverDao from interface to class and register a bean with bean annotation. Still no luck. I tried to move the VerverDao from the dao package to the root package (the same as the Main class) and still no luck.
So if someone could please help me understand the error message, it would make my day.
This is my structure:
This is my code:
Probably some of the annotation is wrong as well, since I'm not used to Spring Boot, in advance thanks for correcting me on the use of these
It is also worth mentioning that I'm using Lombok as well on this project.
Main.java
#ComponentScan("com.gambinomafia")
#SpringBootApplication
public class Main extends SpringBootServletInitializer {
public static void main(String[] args) {
new Main().configure(new SpringApplicationBuilder(Main.class)).run(args);
}
}
Configuration.java
#Component
public class Configuration extends ResourceConfig {
public Configuration() {
register(VerverResourceImpl.class, VerverResource.class);
register(VerverController.class);
register(VerverDao.class);
}
}
VerverResource.java
#Resource
#Path("verver")
public interface VerverResource {
#GET
#Path("/{userid}")
#Produces(MediaType.APPLICATION_JSON)
String getRefferingUrl(#PathParam("userid") int userid);
}
VerverResourceImpl.java
#AllArgsConstructor(onConstructor = #__({#Inject}))
public class VerverResourceImpl implements VerverResource {
private VerverController controller;
#Override
public String getRefferingUrl(int userid) {
log.info("Collection reciever url for user id: {}", userid);
return controller.getRefferingUrl(userid);
}
}
VerverController.java
#Controller
#AllArgsConstructor
public class VerverController {
private VerverDao ververDao;
public String getRefferingUrl(int userid) {
User user = ververDao.getUsername(userid);
if (user.getUsername().isEmpty()) {
throw new NotFoundException("Did not find any user with id " + userid);
}
return "<url-to-site>/?verv=" + user.getUsername();
}
}
VerverDao.java
#AllArgsConstructor
public class VerverDao {
#Value("spring.datasource.url")
private String dbcon;
public User getUsername(int userid) {
Jdbi jdbi = Jdbi.create(dbcon);
return jdbi.withHandle(handle -> handle.createQuery(
"SELECT id, brukernavn FROM t_user WHERE id = :id")
.bind("id", userid)
.mapToBean(User.class)
.findOnly());
}
}
Feel free to ask for more information, if there is missing some information in the topic. I will try to answer as fast as possible.
First at all, you're setting a #ComponentScan with a wrong package in your Application class.
#ComponentScan("com.gambinomafia")
#SpringBootApplication
And, according to the picture, it has to be:
#ComponentScan("com.project.example")
#SpringBootApplication
EDIT: the use of #ComponentScan by #M.Deinum
Because of the Application Class is in the root package and #SpringBootApplication already contains #ComponentScan, It isn't needed to declare #ComponentScan.
Second, instead of use a DAO you can use Repositories. There is more information here: Spring Boot Repositories.
Third, to inject your objects you can use #Autowired over the constructor.
#Controller
public class VerverController
private VerverDao ververDao;
#Autowired
public VerverController(VerverDao ververDao) {
this.ververDao = ververDao;
}
}
There is more information here.
Log clearly says
VerverController required a bean of type 'com.project.example.dao.VerverDao' that could not be found.
It means there is no bean of type com.project.example.dao.VerverDao
Add #Repository on top of VerverDao to resolve the issue.
#Repository
#AllArgsConstructor
public class VerverDao {
}
Note: Ensure VerverDao is in component scanning path as per your package structure.

Categories