Java, Springboot, MongoDB extend SimpleMongoRepository (2020) - java

I've found many problems with this here in Stackoverflow.
But they are all in few years back. Hoping to find an updated solution.
I'm Extending SimpleMongoRepository in my own class to add some custom methods
Here is my code. MongoHelper.java
package com.customlibrary.mongodblibrary.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
#Component
public class MongoHelper<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> implements
CustomerRepository<T , ID> {
/**
* Creates a new {#link SimpleMongoRepository} for the given {#link MongoEntityInformation} and
{#link MongoTemplate}.
*
* #param metadata must not be {#literal null}.
* #param mongoOperations must not be {#literal null}.
*/
public MongoHelper(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
super(metadata, mongoOperations);
}
public void customMeth(){
System.out.println("test");
}
}
Here is my code. CustomerRepository.java
#Repository
public interface CustomerRepository<Customer, String> extends MongoRepository<Customer, String> {
}
And I already put this in my Main
#EnableMongoRepositories(repositoryBaseClass = MongoHelper.class)
But there's a error showing up
Parameter 0 of constructor in com.customlibrary.mongodblibrary.service.MongoHelper required a bean of type 'org.springframework.data.mongodb.repository.query.MongoEntityInformation' that could not be found.
Hoping Someone can give me a solution

Use #NoRepositoryBean instead of #Component for MongoHelper since MongoHelper is supposed to be a base class to be extended and not a bean managed by Spring

Related

How to get Repository Interface object back from SimpleJpaRepository<T,ID> object with proxy resolution

Repository Class
#Repository
public interface AllFileRepository extends JpaRepository<AllFile, Long> {
#Query("SELECT a From AllFile a where a.guid = :guid")
AllFile findByGuid(#Param("guid") String guid);
}
Service Class
#Service
#Data
public class PipelineService implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Autowired
AllFileRepository allFileRepository;
}
Creating object SimpleJpaRepository<AllFile, Long>
PipelineService pipelineService = new PipelineService();
void methodX() {
AnnotationConfigApplicationContext applicationContext = (AnnotationConfigApplicationContext)
ApplicationContextUtils.getApplicationContext();
AutowireCapableBeanFactory autowireCapableBeanFactory =
applicationContext.getAutowireCapableBeanFactory();
autowireCapableBeanFactory.autowireBean(pipelineService);
JpaRepository<AllFile, Long> jpaRepository = (SimpleJpaRepository<AllFile, Long>)
AopProxyUtils.getSingletonTarget(pipelineService.getAllFileRepository());
// (AllFileRepository) jpaRepository casting causes ClassCastException
}
Exception
java.lang.ClassCastException: org.springframework.data.jpa.repository.support.SimpleJpaRepository cannot be cast to ....repository.AllFileRepository
How to get an object of AllFileRepository interface? where I can access findByGuid("");
UPDATE
I am able to get the object of SimpleJpaRepository<AllFile, Long> belonging to interface AllFileRepository which inturn extends JpaRepository
public void initialize() {
AnnotationConfigApplicationContext applicationContext = (AnnotationConfigApplicationContext) ApplicationContextUtils
.getApplicationContext();
EntityManager em = applicationContext.getBean(EntityManager.class);
AllFileRepository allFileRepository = new JpaRepositoryFactory(em).getRepository(AllFileRepository.class);
allFileRepository.findByGuid(""); // Method is accessible here but the object is proxy
SimpleJpaRepository<AllFile, Long> simpleJpaRepository = (SimpleJpaRepository<AllFile, Long>) (AopProxyUtils
.getSingletonTarget(allFileRepository)); // But proxy resolution yeilds SimpleJpaRepository cannot
// explicitly cast to AllFileRepository
((AllFileRepository) simpleJpaRepository).findByGuid(""); // class
// org.springframework.data.jpa.repository.support.SimpleJpaRepository
// cannot be cast to class
// com.example.spingaoprepository.repository.AllFileRepository
// (org.springframework.data.jpa.repository.support.SimpleJpaRepository
// and
// com.example.spingaoprepository.repository.AllFileRepository
// are in unnamed module of loader 'app'
}
Here is a link to sample program
There is no use in trying to cast incompatible types into each other. This is not a Spring problem, it is Java basics. I already told you how to solve that in Spring, too: You need to provide a class actually implementing AllFileRepository and make sure Spring Data JPA uses it as a repository instead of the interface. In order to do that, you need to
change the interface annotation from #Repository to #NoRepositoryBean,
create class #Repository AllFileRepositoryImpl and there provide an implementation of AllFile findByGuid(String guid) doing something meaningful.
Then you can easily cast the way you want because your proxy's target object will be an AllFileRepositoryImpl instance.
I sent you a pull request which you just need to accept. The classes changed in the relevant commit #5705cbb look as follows:
package com.example.spingaoprepository.repository;
import com.example.spingaoprepository.model.AllFile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.data.repository.NoRepositoryBean;
#NoRepositoryBean
public interface AllFileRepository extends JpaRepository<AllFile, Long> {
#Query("SELECT a From AllFile a where a.guid = :guid")
AllFile findByGuid(#Param("guid") String guid);
}
package com.example.spingaoprepository.repository;
import com.example.spingaoprepository.model.AllFile;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
#Repository
public class AllFileRepositoryImpl extends SimpleJpaRepository<AllFile, Long> implements AllFileRepository {
public AllFileRepositoryImpl(EntityManager em) {
super(AllFile.class, em);
}
#Override
public AllFile findByGuid(String guid) {
System.out.println("Finding AllFile by GUID " + guid);
return null;
}
}
package com.example.spingaoprepository.serializable;
import com.example.spingaoprepository.repository.AllFileRepository;
import com.example.spingaoprepository.service.PipelineService;
import com.example.spingaoprepository.utils.ApplicationContextUtils;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
public class PipelineConfigurer {
private ApplicationContext applicationContext = ApplicationContextUtils.getApplicationContext();
private PipelineService pipelineService = applicationContext.getBean(PipelineService.class);
public void initialize() {
AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
autowireCapableBeanFactory.autowireBean(pipelineService);
AllFileRepository allFileRepository = (AllFileRepository) AopProxyUtils
.getSingletonTarget(pipelineService.getAllFileRepository());
allFileRepository.findByGuid("XY-123");
}
}
You are instantiating your PipelineService using the new keyword and then manually getting the Spring context in your methodX().
In principle, of course you 'could' do it all manually without Spring. But given both your repository and service are Spring beans, then it's better to let Spring handle the bean lifecyle. It's certainly easier anyway.
As PipelineService is a Spring bean, you should really make any class that uses it Spring aware too. So just annotate the class that with a Spring annotation like #Component, #Service, or perhaps #RestController if it's a controller.
If you insist on creating the bean manually then try -
ApplicationContext context = new AnnotationConfigApplicationContext();
PipelineService pipelineService = context.getBean(PipelineService.class);
Using #Autowired you are injecting an object implementing AllFileRepository. This singleton was created at startup hence you can just use is with allFileRepository.findByGuid("");

SAP Hybris Commerce 6.2 Cuppy Project Setup Issues

Name clash: The method convertAll(Collection<SOURCE>) of type GenericCollectionConverter has the same erasure as convertAll(Collection<? extends SOURCE>) of type Converter but does not override it
Below files giving the error above while doing Ant Clean All installation in CMD, using Java 1.8 and WS-Core 2.3 jar
package de.hybris.platform.cuppy.web.converters;
import de.hybris.platform.servicelayer.dto.converter.GenericConverter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* #author andreas.thaler
*
*/
public class GenericCollectionConverter<SOURCE, TARGET> extends GenericConverter<SOURCE, TARGET> implements
CollectionConverter<SOURCE, TARGET>
{
#Override
public List<TARGET> convertAll(Collection<SOURCE> sources)
{
// YTODO Auto-generated method stub
return null;
}
}
/**
*
*/
package de.hybris.platform.cuppy.web.converters;
import de.hybris.platform.servicelayer.dto.converter.Converter;
import java.util.Collection;
import java.util.List;
/**
* #author andreas.thaler
*
*/
public interface CollectionConverter<SOURCE, TARGET> extends Converter<SOURCE, TARGET>
{
/**
* Converts all sources to new instances of target type.
*/
List<TARGET> convertAll(final Collection<SOURCE> sources);
}

Aspect Oriented Programming in Spring error when I implements interface

I'm studying Aspect Oriented Programming in Spring with #AspectJ
I write an example but when I run it I've an error
Here are the class that I write
package concert;
/**
*
* #author phate
*/
public interface Performance {
public void perform();
}
Class PerformanceImpl implements the Performance interface and implements perform method
package concert;
import org.springframework.stereotype.Service;
/**
*
* #author Dennis A. Boanini
*/
#Service
public class PerformanceImpl implements Performance{
#Override
public void perform() {
System.out.println("perform");
}
}
Class Audience is annotated with #Aspect and declare some Advice
package concert;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
*
* #author Dennis A. Boanini
*/
#Component
#Aspect
public class Audience {
#Before("execution(* concert.Performance.perform(..))")
public void silenceCellPhones(){
System.out.println("Silencing cell phones");
}
#Before("execution(* concert.Performance.perform(..))")
public void takeSeats(){
System.out.println("Taking seats");
}
#AfterReturning("execution(* concert.Performance.perform(..))")
public void applause(){
System.out.println("CLAP CLAP CLAP");
}
#AfterThrowing("execution(* concert.Performance.perform(..))")
public void demandRefund(){
System.out.println("Demanding a refund");
}
}
Class ConcertConfig is the bean that autoproxy
package concert;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
*
* #author Dennis A. Boanini
*/
#Configuration
#EnableAspectJAutoProxy
#ComponentScan
public class ConcertConfig{
#Bean
public Audience audience() {
return new Audience();
}
}
And this is the main class
public class Turing {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(ConcertConfig.class);
ctx.refresh();
Performance userService = ctx.getBean(PerformanceImpl.class);
userService.perform();
}
}
If I run I receive this error
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [concert.PerformanceImpl] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:374)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:334)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1088)
at com.phate.spring.aop.example.Turing.main(Turing.java:32)
But if I eliminate the interface everything work correctly, why?

Getting #Autowired error

I'm getting an error whenever I'm using #Autowired annotation. The root error i get is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [jp.co.vmt.qt.C0002.C0002Dao] 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)}
My interface is
/**
*
*/
package jp.co.vmt.qt.C0002;
import java.util.List;
import jp.co.vmt.qt.model.TmtProject;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
/**
* #author WINDOWS
*/
public interface C0002Dao extends JpaRepository<TmtProject, Long> {
#Query("SELECT PROJECT_ID, PROJECT_NAME FROM TmtProject")
public List<TmtProject> getAllProjects();
}
And my implementing class is
/**
*
*/
package jp.co.vmt.qt.C0002;
import java.util.List;
import jp.co.vmt.qt.model.TmtProject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Repository;
/**
* #author WINDOWS
*/
#Repository
public class C0002Service implements C0002Dao {
#Autowired
private C0002Dao c0002Dao;
/*
* (non-Javadoc)
* #see jp.co.vmt.qt.C0002.C0002Dao#getAllProjects()
*/
#Override
public List<TmtProject> getAllProjects() {
return this.c0002Dao.getAllProjects();
}
... other methods from extended interface
}
And here is where I used c0002Service
/**
*
*/
package jp.co.vmt.qt.C0002;
import java.util.List;
import jp.co.vmt.qt.model.TmtProject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* #author WINDOWS
*/
#Component
public class C0002Logic {
#Autowired
private C0002Dao c0002Service;
public String getProjectList() throws Exception {
List<TmtProject> projectList = this.c0002Service.getAllProjects();
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(projectList);
return jsonString;
}
}
I have my C0002Logic autowired in my controller which is not shown here.
To my understanding, I created an interface (C0002Dao) and an implementing class (C0002Service) of that interface, which I marked with #Repository and I am autowiring the service to my Logic class (C0002Logic). However, I'm getting the error shown above. Any ideas on where I went wrong and how to solve them? Thanks
The problem is I believe
In C0002Service,
#Autowired
private C0002Dao c0002Dao;
U r trying to inject to C0002Dao at the time qualifying bean (instance of C0002Service) is about to be registered.

How can this DAO abstract method work without implementation?

I have a interface DAO class method that extends CrudRep working without implementation. It is a MVC project with Spring Framework and Hibernate ORM. Here is class:
package eu.execom.collections.dao;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import eu.execom.collections.model.Book;
import eu.execom.collections.model.User;
public interface BookDAO extends CrudRepository<Book, Long> {
public List<Book> findByUser(User user);
}

Categories