Spring Hibernate won't implement Repository Class from Interface - spring

I have two separate projects. One project contains my Application logic and Controllers in org.patrick.application, and one separate project contains my Hibernate entities, Dao, and models in org.patrick.hibernate. My problem is that Spring will not instantiate a implementing class for my CrudRepository.
Here is my Application.java class annotations in my Application project:
package org.patrick.application;
#SpringBootApplication
#Configuration
#EnableAutoConfiguration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = { "org.patrick.hibernate" })
#EntityScan(basePackages = { "org.patrick.hibernate" })
#ComponentScan(basePackages = { "org.patrick.hibernate", "org.patrick.application" })
These annotations should scan my second Hibernate project for all of my Hibernate objects.
My Hibernate repository looks like this:
package org.patrick.hibernate;
#Repository
public interface PatrickDao extends CrudRepository<MyModel, Long>
This repository does not have a class implementation. I am expecting Spring to populate this implementation for me.
Now, inside of my application org.patrick.application, I am trying to use the Dao like so:
package org.patrick.application;
#Autowired
private PatrickDao patrickDao;
This is causing my Application project to fail to start because of the following error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency [org.patrick.hibernate.PatrickDao]: expected at least 1 bean which qualifies as autowire candidate.
I know that the core problem is that Spring is not implementing this interface -
because if I provide my own PatrickDaoImpl in the org.patrick.hibernate package, then the Application project will start just fine. This confuses me because I have the proper annotations on my Application.java class, and yet the Repository cannot be implemented by Spring for some reason.
Is there anything further I need to do in order to get Spring to implement the class for my Repository interface? In previous testing, this behavior works if everything is under the same package.

I found the problem. For this particular Model, the definition looked as such:
package org.patrick.hibernate;
public class MyModel implements Serializable {}
This Model did not have the #Entity annotation. If this annotation is missing, then Spring will give no warnings as to why it cannot implement the repository interface. In my case, it simply threw the NoSuchBeanDefinitionException exception.
I updated my Model with the proper annotations:
package org.patrick.hibernate;
#Entity
public class MyModel implements Serializable {}

Related

Should we use #Component on #Entity class in Spring boot

Well i am a newbie in spring boot. I was working on a project where I needed to #Autowired my Entity in a controller class. But I ended up with error:
Field repository in abc required a bean of type 'xyz' that could not be found.
But it solved after adding #Component in Entity class.
So my questions are:
Why Spring boot was not scanning my Entity class as it was under #SpringBootApplication declaration?
When and where we should use #Component annotation in our application?
Use #Component to flag your Pojo as Spring Bean, so that you inject it into other beans with #Autowired
Use #Entity to flag your Pojo as JPA or Spring Data managed bean to read or write it to a database

Dynamic autowire in /src/groovy

I want to be able to include Services in my Groovy Classes in /src/groovy
I found a solution with :
myBean(MyBean) { bean ->
bean.autowire = 'byName'
}
But I dont want to make this entry in the resources.groovy for all Class, so is there a Solution to Autowire all classes in a specific folder?
I'm using grails 2.4.3
This seems to be similar to this question: Grails 2.x service injection in Groovy/src
What we use and is proposed there is to get the service via the application context:
import grails.util.Holders
...
def myService = Holders.grailsApplication.mainContext.getBean 'myService'
It's not completely auto-wired, but seems to be the best way to get services into src/groovy.
Edit: also works for Grails 3
You can make a class com.example.MyClass in src/groovy a Spring bean by adding the following to BuildConfig.groovy
grails.spring.bean.packages = ['com.example']
and annotating the class with #Component, e.g.
#Component
class MyClass {
#Value('${conf.apiVersion}')
String apiVersion
#Autowired
SomeService someService
}
As shown above, you can dependency-inject the class with the usual Spring annotations such as #Value and #Autowired. I find this a much more convenient way to register a Spring bean than modifying resources.groovy.

how Spring boot explicitly not load a class if it's not a web project?

An independent common project A which supply common configuration, inside it there is a class
#RestController
public class CustomErrorController implements ErrorController {
#Autowired
private ErrorAttributes errorAttributes;
//...
}
Now there is another project B which depend on above project A, but this is not a web project only execute some business logic then exit. So in application.properties I have this configuration:
spring.main.web_environment=false
but when run project B, it failed because this exception:
No qualifying bean of type [org.springframework.boot.autoconfigure.web.ErrorAttributes] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
So how to solve this problem? Could exclude CustomErrorController in B's pom.xml or if it's not a web project could not load CustomErrorController?
spring.main.web_environment=false disable the embedded container even if it is present in your project. It does not perform black magic to prevent your classes to be instantiated.
If you are using component scan and you provide classes that require a web environment it will fail (as you just saw). Maybe you need to refactor your project in several modules and isolate the web part in a separate project?
exclude CustomErrorController class
#ComponentScan(basePackages = "com.foo",
excludeFilters = {#ComponentScan.Filter(value = ProjectAApplication.class,type = FilterType.ASSIGNABLE_TYPE),
#ComponentScan.Filter(value = CustomErrorController.class, type = FilterType.ASSIGNABLE_TYPE)})
#SpringBootApplication
public class ProjectBApplication implements CommandLineRunner {

Spring Boot NoUniqueBeanDefinitionException

I am converting a Java EE project to Spring Boot 1.1.9. Before converting, I was used to CDI 1.2 for Dependency Injection.
I have an interface :
public interface AdminManager<V extends AdminView>
I also have a few implementations of this interface. They look like this :
#Repository
#Transactional(propagation=Propagation.REQUIRED)
public class DBRuleManager implements AdminManager<AdminRuleView>
#Repository
#Transactional(propagation=Propagation.REQUIRED)
public class DBFlagLogicManager implements AdminManager<AdminFlagLogicView>
Now, I have coded a REST endpoint, that is supposed to use the DBRuleManager:
#Controller
#RequestMapping("/admin/rule")
public class RestAdminRule {
#Inject
private AdminManager<AdminRuleView> manager;
}
When I run mvn spring-boot:run I get the following NoUniqueBeanDefinitionException :
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.company.server.admin.AdminManager] is defined: expected single matching but found 2: DBRuleManager,DBFlagLogicManager
I've read that Spring 4 is supposed to manage this kind of situation. What's the problem then? This was working well using CDI.
When trying to solve another problem (about proxies for #Transactional implementations), I found a way to get rid of this issue.
I used this parameter :
#EnableTransactionManagement(proxyTargetClass=true)
And then I was able to inject my AdminManager<AdminRuleView> directly. I don't understand why, though...

How to Autowire repository interface from a different package using Spring Boot?

I am new to Spring Boot and want to autowire a repository from a different package in a Rest Controller. It seems that when I place the interface and implementation in a different package the actual controller the autowire seems to fail.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.acme.repository.RawDataRepository] found for dependency:..
Controller:
package com.acme.controller;
import com.acme.repository.RawDataRepository;
// imports removed!
#RestController
#EnableAutoConfiguration
#ComponentScan("com.acme")
public class DataCollectionController {
#Autowired
private RawDataRepository repository;
// code removed!
}
I have tried to use the #ComponentScan annotation but this gives no solution.
Any idea what i am missing? Whenever i put the interface into the package in which the controller resides then all goes well.
If you have Spring Data #Repositories in a different package you have to explicitly #EnableJpaRepositories (or replace "Jpa" with your own flavour). Boot takes it's defaults from the package containing the #EnableAutoConfiguration so it might work to just move that class as well.
You have to use following two annotations
#EnableJpaRepositories(basePackages = "package-name")
#EntityScan(basePackages = "package-name")
EnableJpaRepositories will enable repository if main class is in some different package.
You need to use EntityScan as well to point to package where you have your entity beans or else it will fail with 'Bean is not of managed type' error.
Spring Boot Provides annotations for enabling Repositories.
So whenever someone uses any Repository (it can be JPARepository , CassandraReposotory) it should be enabled in Application Class itself.
Example:
#EnableCassandraRepositories("package name")
#EnableJpaRepositories("package name")
After providing the above annotations, the container takes care of injecting beans for repositories as well.

Resources