Error running UT - BeanCreationException No property update found Custom Repository - spring-boot

While running below UT CarRepositoryTest seeing following error Is I am missing any configuration here?
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'itemRepository': Invocation of init
method failed; nested exception is java.lang.IllegalArgumentException:
Failed to create query for method public abstract void
com.dms.repository.interfaces.CustomItemRepository.update(java.util.List)!
No property update found for type InventoryItemEntity!
Annotated with UT with EnableJpaRepositories (basePackages and repositoryFactoryBeanClass)
#RunWith(SpringRunner.class)
#DataJpaTest
#EnableJpaRepositories(basePackages = {"com.dms.repository",
"com.dms.repository.interface"},
repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
#EntityScan(basePackageClasses = Car.class)
public class CarRepositoryTest {
#Autowired private CarRepository repository;
#Autowired private TestEntityManager testEntityManager;
#Test
public void getCar_returnsCarDetails() throws Exception {
final String s = GenerateUUID.generateUUID();
Car savedCar = testEntityManager.persistFlushFind(new Car(s, "hybrid"));
Car car = this.repository.findByName(s);
assertNotNull(car);
assertThat(car.getName(), is(s));
assertThat(car.getType(), is("hybrid"));
}
}
#Configuration
#EnableJpaRepositories( basePackages = "com.dms.repository",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager",
repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
#EnableTransactionManagement
public class JpaConfiguration {
...
}
package com.dms.repository;
#Repository
public class ItemRepositoryImpl implements CustomItemRepository {
#PersistenceContext
private EntityManager em;
#Override
public void update(List<ItemDTO> dtos) {
...
}
}
package com.dms.repository.interfaces;
public interface CustomItemRepository {
void update(List<ItemDTO> dtos);
}
package com.dms.repository;
public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T,
I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {
}
package com.dms.repository;
public class BaseRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
private final EntityManager em;
#Transactional
#Override
public Specification<T> searchUsingRSQLParser(String query) {
return new RSQLParser().parse(query)
.accept(new CustomRsqlVisitor<>());
}
}
What configuration should be added/modify so that UT should not fail with a custom repository?

Related

Why can't #Autowired a JPA repository - Spring boot + JPA

I'm giving this error:
Parameter 0 of constructor in x.microservice.module.business.application.BusinessCreator required a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=false)
Action:
Consider defining a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' in your configuration.
The controller:
#Slf4j
#RestController
public final class BusinessPostController {
#Autowired
private BusinessCreator creator;
#PostMapping(value = "/business")
public ResponseEntity create(#RequestBody Request request){
BusinessCreatorDto businessCreatorDto = new BusinessCreatorDto(IdentifierEpoch.generate(),request.getName());
return ResponseEntity.ok(
creator.create(businessCreatorDto)
);
}
}
The Application Layer:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}
In the Infrastructure layer
#Repository
public abstract class HibernateJpaRepository implements JpaRepository<Business, Long> {
}
The boot Application:
#EnableJpaRepositories
#SpringBootApplication
public class MicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceApplication.class, args);
}
}
All dependencies are resolved and the others classes I believe that are irrellevant.
Any suggestions? Thank you very much
Probably, the error cause is HibernateJpaRepository - it has to be an interface that extends JpaRepository.
You could write your own Repository in a interface:
#Repository
public interface HibernateJpaRepository extends JpaRepository < Business, Long > {
}
Then your Class:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}

#Autowired annotation not working for one #Controller class and working for others

I have three #RestController classes, for two of them the #Autowired is injecting the bean, but for one it is not. I don't know what the issue is, as few hours ago the same code was working fine.
package com.learn.service;
package com.learn.service;
#Service
#Transactional
public class RoleService {
#Autowired
private RoleJpaRepository roleJpaRepository;
public List<Role> findAll(){
return roleJpaRepository.findAll();
}
}
the controller for Role
package com.learn.controller;
#RestController
#RequestMapping("/roles")
public class RoleController {
#Autowired
private RoleService roleService;
#RequestMapping(method = RequestMethod.GET)
private List<Role> findAll() {
System.out.println(roleService); // roleService is null here and NullPointerException is thrown from below method call.
return roleService.findAll();
}
}
Configuration class for Service
package com.learn.springConfig;
#Configuration
#ComponentScan("com.learn.service")
public class ServiceConfig {
public ServiceConfig() {
super();
}
}
the runner
#SpringBootApplication
#Import({
ContextConfig.class,
PersistenceJpaConfig.class,
ServiceConfig.class,
WebConfig.class,
SecurityConfig.class
})
public class WebservicesLearningApplication {
public static void main(String[] args) {
SpringApplication.run(WebservicesLearningApplication.class, args);
}
}
For the same configurations, the controller for User is working fine whose Service layer exists in the same package as that of Role.
package com.learn.controller;
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserService userService;
#RequestMapping(method = RequestMethod.GET)
public List<User> findAll() {
System.out.println(userService);
List<User> users = userService.findAll();
return users;
}
Service layer
package com.learn.service;
#Service
#Transactional
public class UserService {
#Autowired
private UserJpaRepository userJpaRepository;
public List<User> findAll(){
return userJpaRepository.findAll();
}
}
Accessing the localhost:8080/api/users is successful but localhost:8080/api/roles gives NullPointerException
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.learn.controller.RoleController.findAll(RoleController.java:30) ~[classes/:na]............
Update1:
Web configuration class
#Configuration
#ComponentScan(basePackages = {"com.learn.controller"})
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
public WebConfig() {
super();
}
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
Optional<HttpMessageConverter<?>> convertFound = converters.stream().filter(c -> c instanceof AbstractJackson2HttpMessageConverter).findFirst();
if(convertFound.isPresent()) {
final AbstractJackson2HttpMessageConverter converter = (AbstractJackson2HttpMessageConverter) convertFound.get();
converter.getObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
converter.getObjectMapper().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
}
}
screenshot of project structure
Update2 : I tried using the same UserService using #Autorired in a jUnit test case, and everything is working there. No nullpointer exception.
#ContextConfiguration(classes = {PersistenceJpaConfig.class, ContextConfig.class, ServiceConfig.class})
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class RoleTest {
#Autowired
private RoleService roleService ;
#Test
public void checkIfAllRolesCanBeRetrieved() {
List<Role> roles = roleService.findAll();
Assert.assertNotNull(roles);
}
}
This happened to me! in my case I had a controller using service,The service used a method of a class that did not have a #service,#controller or another annotation and I inject in service then when I use parent service error null occurred.
I hope that it will be used

Spring Boot JPA with REST Service

I know that such questions were asked (Did not find handler method ), but after trying multiple solutions I'm still stucked.
So my problem is: I can't use both REST and JPA in my project.
com.db.ruf: WRepository.class:
#NoRepositoryBean
#Component
public interface WRepository <T, ID extends Serializable>
extends JpaRepository<T, ID> {
}
com.db.ruf: WRepositoryImpl.class:
public class WRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements WRepository<T, ID> {
private EntityManager entityManager;
// There are two constructors to choose from, either can be used.
public WRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
// This is the recommended method for accessing inherited class dependencies.
this.entityManager = entityManager;
}
}
com.db: MyRepositoryFactoryBean.class
public class MyRepositoryFactoryBean <R extends JpaRepository<T, I>, T, I extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
/**
* Creates a new {#link JpaRepositoryFactoryBean} for the given repository interface.
*
* #param repositoryInterface must not be {#literal null}.
*/
public MyRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
super(repositoryInterface);
}
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new MyRepositoryFactory(entityManager);
}
private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {
private EntityManager entityManager;
public MyRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new WRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), entityManager);
}
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the JpaRepositoryFactory
//to check for QueryDslJpaRepository's which is out of scope.
return WRepository.class;
}
}
}
com.rest.: WebadminRESTController.class
#RestController
#Component
public class WebadminRESTController {
#Autowired
WRepository<ExternalLink, Long> wRepositoryImpl;
#RequestMapping(value = "/allExternalLinks", method = RequestMethod.GET)
public ResponseEntity<?> allExternalLinks() {
...
}
}
com:
#SpringBootApplication
#EnableAutoConfiguration
#EnableJpaRepositories(basePackages = "com.db.ruf", repositoryFactoryBeanClass = MyRepositoryFactoryBean.class)
#ComponentScan(basePackages = "com", resourcePattern = "com.*")
#EntityScan({"com.db"})
public class WebadminApplication {
public static void main(String[] args) {
SpringApplication.run(WebadminApplication.class, args);
}
}
In this case I get:
Did not find handler method for [/allExternalLinks]
If I change
#ComponentScan(basePackages = "com", resourcePattern = "com.*") to #ComponentScan(basePackages = "com") or #ComponentScan I get:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'com.db.ruf.WRepository' available: expected at least 1 bean which qualifies
as autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
I really don't know what's wrong.
Could anyone be so kind to explain it?
Thank you in advance
Use #Repository on WRepositoryImpl.java. And edit WebadminRESTController.java:
#Autowired
WRepositoryImpl<ExternalLink, Long> wRepositoryImpl;
Accidentally I found solution (don't think that it is the best one, but at least it works):
public interface ExternalLinksRepo extends CrudRepository<ExternalLink, Long> {
...
}
and:
public class WebadminRESTController {
#Autowired
ExternalLinksRepo wRepositoryImpl;
...}
Then wRepositoryImpl is automatically created as instance of WRepositoryImpl
Thanks to all, especially to Cepr0

Spring boot Autowiring service implementation in a bean fails

I'm trying to autowire a service implementation in one of my beans, but I keep getting a NoSuchBeanDefinitionException. This is my code:
Repository:
#Repository
public interface GlobalPropertiesRepository extends BaseRepository<GlobalProperties, Long>{
}
Service:
public interface GlobalPropertiesService {
GlobalProperties findOne(Long id);
}
Base Repository:
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;
import java.io.Serializable;
import java.util.List;
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
void delete(T deleted);
List<T> findAll();
List<T> findAll(Iterable<ID> ids);
T findOne(ID id);
T save(T persisted);
<S extends T> S saveAndFlush(S entity);
}
Service Impl:
#Service("globalPropertiesService")
public class GlobalPropertiesServiceImpl implements GlobalPropertiesService{
#Autowired
GlobalPropertiesRepository globalPropertiesRepository;
#Override
public GlobalProperties findOne(Long id) {
return globalPropertiesRepository.findOne(id);
}
}
And then I autowire the implementation in one of my beans as below:
public class GlobalPropertiesLoader {
#Autowired
private GlobalPropertiesService globalPropertiesService;
private GlobalProperties globalProperties;
#PostConstruct
public void init(){
globalProperties = globalPropertiesService.findOne(1L);
}
public GlobalProperties getGlobalProperties(){
return globalProperties;
}
}
Finally, this is my Configuration class:
#Configuration
public class AppServiceConfig {
public AppServiceConfig() {
}
// Global properties
#Bean(name="globalPropertiesLoader")
public GlobalPropertiesLoader globalPropertiesLoader(){
return new GlobalPropertiesLoader();
}
}
This is my SpringBoot class:
#SpringBootApplication
#ComponentScan(basePackages="...")
public class TrackingService {
private static final Logger LOGGER = LoggerFactory.getLogger(TrackingService.class);
static AnnotationConfigApplicationContext context;
public static void main(String[] args) throws Exception {
SpringApplication.run(TrackingService.class, args);
ClassPathScanningCandidateComponentProvider provider =
new ClassPathScanningCandidateComponentProvider(true);
String basePackage = "...";
Set<BeanDefinition> components = provider.findCandidateComponents(basePackage);
for (BeanDefinition component : components) {
LOGGER.info("Component: "+component.getBeanClassName());
}
context = new AnnotationConfigApplicationContext();
context.refresh();
context.close();
}
}
Now, when I try to start the application, I get the following error in my GlobalPropertiesLoader bean:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [GlobalPropertiesService] 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)}

Spring Data JPA Custom Generic Repository Pattern issue

I have the following configuration in Spring but Autowiring fails due to lack of an init method in the Impl class of the repository. Spring shouldn't be attempting to init the bean by a constructor, but it should be using the Factory ... I've missed some simple configuration... or I have ran into a bug.
I am trying to achieve a single generic repository where all repositories can share methods and specific ones that are particular to my mapped domain classes...
Here is my error:
Error creating bean with name 'auditRepositoryImpl' defined in file AuditRepositoryImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.domain.biz.dao.impl.AuditRepositoryImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.domain.biz.dao.impl.AuditRepositoryImpl.<init>()
On another side note, it looks like my CustomFactory isn't being picked up.
2014-07-05 08:16:48,343 DEBUG org.springframework.data.repository.config.RepositoryComponentProvider Identified candidate component class: file [InventoryRepository.class]
...
2014-07-05 08:16:48,366 DEBUG org.springframework.data.repository.config.RepositoryBeanDefinitionBuilder Registering custom repository implementation: auditRepositoryImpl AuditRepositoryImpl
2014-07-05 08:16:48,367 DEBUG org.springframework.data.repository.config.RepositoryConfigurationDelegate Registering repository: auditRepository - Interface: AuditRepository - Factory: org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean
//Spring Java config
#Configuration
#EnableScheduling
#EnableSpringConfigured
#Import(EnvConfiguration.class)
#EnableAspectJAutoProxy
#EnableJpaRepositories(repositoryFactoryBeanClass = DefaultRepositoryFactoryBean.class, basePackages = { "com.domain.biz.dao" }, repositoryImplementationPostfix = "Impl")
#EnableCaching
#EnableTransactionManagement(proxyTargetClass = true)
#ComponentScan(basePackages = { "com.domain.biz" })
#Order(2)
public class AppConfiguration extends CachingConfigurerSupport implements LoadTimeWeavingConfigurer
...
#NoRepositoryBean
public interface GenericRepository<T extends Serializable, I extends Serializable>
extends JpaRepository<T, I> {
...
#NoRepositoryBean
public abstract class AbstractRepositoryImpl<T extends Serializable, I extends Serializable>
extends SimpleJpaRepository<T, I> implements GenericRepository<T, I> {
private static Logger log = LoggerFactory
.getLogger(AbstractRepositoryImpl.class);
private Class<T> clazz;
#Autowired
EntityManager entityManager;
#Autowired
SessionFactory sessionFactory;
public AbstractRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
}
public AbstractRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
}
...
#NoRepositoryBean
// #Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericRepositoryImpl<T extends Serializable, I extends Serializable>
extends AbstractRepositoryImpl<T, I> implements GenericRepository<T, I> {
...
public interface AuditRepositoryCustom {
public Audit audit(Audit audit);
public interface AuditRepository extends GenericRepository<Audit, Long>, AuditRepositoryCustom {
public class DefaultRepositoryFactoryBean<R extends JpaRepository<T, I>, T extends Serializable, I extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
private static class RepositoryFactory<T extends Serializable, I extends Serializable>
extends JpaRepositoryFactory {
private EntityManager entityManager;
public RepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
#Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
// The RepositoryMetadata can be safely ignored, it is used by the
// JpaRepositoryFactory
// to check for QueryDslJpaRepository's which is out of scope.
return GenericRepository.class;
}
#Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
return new GenericRepositoryImpl<T, I>(
(Class<T>) metadata.getDomainType(), this.entityManager);
}
}
#Override
protected RepositoryFactorySupport createRepositoryFactory(
EntityManager entityManager) {
return new RepositoryFactory(entityManager);
}
The exception is pretty clear about the root cause. Your AuditRepositoryImpl does not have either a no-arg constructor or a constructor annotated with #Inject/#Autowired.
Here is the corrected code in case anyone needs it.
#NoRepositoryBean
public interface GenericRepository<T extends Serializable, I extends Serializable>
extends JpaRepository<T, I> {
Result truncate();
...
#NoRepositoryBean
public abstract class AbstractRepositoryImpl<T extends Serializable, I extends Serializable>
extends SimpleJpaRepository<T, I> implements GenericRepository<T, I> {
public AbstractRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
}
public AbstractRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
}
#Override
public Result truncate() {
...
public class GenericRepositoryImpl<T extends Serializable, I extends Serializable>
extends AbstractRepositoryImpl<T, I> implements GenericRepository<T, I> {
public GenericRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
}
public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
}
...
public interface AuditRepositoryCustom {
public Audit audit(Audit audit);
....
public interface AuditRepository extends GenericRepository<Audit, Long>,
AuditRepositoryCustom {
...
#NoRepositoryBean
public class AuditRepositoryImpl extends GenericRepositoryImpl<Audit, Long>
implements AuditRepositoryCustom {
private static Logger log = LoggerFactory.getLogger(AuditService.class);
public AuditRepositoryImpl(Class<Audit> domainClass, EntityManager em) {
super(domainClass, em);
log.debug("AuditDAO Created...");
// TODO Auto-generated constructor stub
}
#Autowired
public AuditRepositoryImpl(EntityManager em) {
super(Audit.class, em);
}
public AuditRepositoryImpl(
JpaEntityInformation<Audit, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
log.debug("AuditDAO Created...");
// TODO Auto-generated constructor stub
}
#Override
public Audit audit(Audit audit) {
return super.save(audit);
}

Resources