How can I fix bugs in Custom Repository? - spring-boot

I'm trying to make a Custom Repository with spring-data-jpa.
My codes
Repository
#NoRepositoryBean
interface CustomRepository<T, ID : Serializable> : JpaRepository<T, ID> {
fun findBySomeRestrict(id: ID): T?
}
RepositoryImpl
#Transactional(readOnly = true)
class CustomRepositoryImpl<T, ID : Serializable>(
private val entityManager: EntityManager,
jpaEntityInformation: JpaMetamodelEntityInformation<T, ID>
) : SimpleJpaRepository<T, ID>(jpaEntityInformation, entityManager), CustomRepository<T, ID> {
override fun findBySomeRestrict(id: ID): T? {
// TODO
}
}
Main class
#EnableJpaAuditing
#EnableJpaRepositories(repositoryBaseClass = CustomRepositoryImpl::class)
#SpringBootApplication
class ForSubmitApplication
fun main(args: Array<String>) {
runApplication<ForSubmitApplication>(*args)
}
MyErrorMessage
Caused by: java.lang.IllegalStateException: No suitable constructor found on interface com.example.forsubmit.global.custom.CustomRepository to match the given arguments: org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation, jdk.proxy2.$Proxy132. Make sure you implement a constructor taking these
at org.springframework.data.repository.core.support.RepositoryFactorySupport.lambda$instantiateClass$6(RepositoryFactorySupport.java:578) ~[spring-data-commons-2.6.0.jar:2.6.0]
at java.base/java.util.Optional.orElseThrow(Optional.java:403) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.instantiateClass(RepositoryFactorySupport.java:578) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getTargetRepositoryViaReflection(RepositoryFactorySupport.java:542) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:182) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:164) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:75) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:324) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:322) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:230) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.util.Lazy.get(Lazy.java:114) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:328) ~[spring-data-commons-2.6.0.jar:2.6.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144) ~[spring-data-jpa-2.6.0.jar:2.6.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.13.jar:5.3.13]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.13.jar:5.3.13]
... 72 common frames omitted
What I do to fix it
Change the type of constructor to JpaEntityInformation
Decompile the code

It seems you only want to provide the implementation of one method.
In that case you must not set repositoryBaseClass.
Instead you want to follow the steps outlined in the documentation.
Create an interface just containing the custom method(s). You currently don't have that.
Create an implementation of it. You are currently implementing the final Repository interface which is wrong.
Extend your final repository interface from the custom interface created in step 1.

Related

CucumberBackendException: No qualifying bean of type

When trying to run step defs with abstract class contains all the context configuration spring sees 2 differnt beans parent and stepdef
I'm using spring boot version: 2.6.4 , with Junit 5 and cucumber version 7.2.3
#SpringBootTest(classes = CoreApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = AbstractIntegrationTest.Config.class)
#CucumberContextConfiguration
public abstract class AbstractIntegrationTest implements En {}
#Suite
#IncludeEngines("cucumber")
#SelectClasspathResource("com/example/bdd")
#ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.bdd")
public class CucumberIntegrationTest {
}
public class MyStepdefs extends AbstractIntegrationTest{
public MyStepdefs() {
When("^client post to \"([^\"]*)\" with valid data$", (String arg0) -> {
});
Then("^the client receives status code of (\\d+)$", (Integer arg0) -> {
});
}
}
Exception Stack trace:
io.cucumber.core.backend.CucumberBackendException: No qualifying bean of type 'com.orange.ces.core.bdd.AbstractIntegrationTest' available: expected single matching bean but found 2: com.orange.ces.core.bdd.MyStepdefs,com.orange.ces.core.bdd.AbstractIntegrationTest
at io.cucumber.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:124)
at io.cucumber.spring.TestContextAdaptor.stop(TestContextAdaptor.java:107)
at io.cucumber.spring.SpringFactory.stop(SpringFactory.java:161)
at io.cucumber.core.runner.Runner.disposeBackendWorlds(Runner.java:156)
at io.cucumber.core.runner.Runner.runPickle(Runner.java:78)
at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$3(CucumberExecutionContext.java:151)
at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:151)
at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1632)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
at io.cucumber.core.cli.Main.run(Main.java:87)
at io.cucumber.core.cli.Main.main(Main.java:30)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.orange.ces.core.bdd.AbstractIntegrationTest' available: expected single matching bean but found 2: com.orange.ces.core.bdd.MyStepdefs,com.orange.ces.core.bdd.AbstractIntegrationTest
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1271)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at io.cucumber.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:120)
... 30 more
In case you have several step definition classes, you can create a stub class with annotations only
#ContextConfiguration(classes = AbstractIntegrationTest.Config.class)
#CucumberContextConfiguration
public class StubConfig { }
Place it into a separate package and mention it in #CucumberOptions (if you have it)
Another ugly workaround:(

JPA No property findAll found for type Product

My repository:
#Repository
public interface ProductDao extends JpaRepository<Product,Long>,JpaSpecificationExecutor<Product> {
Page<Product> findAll(Specification<Product> specification,Pageable pageable);
}
My service:
...
#Autowired
public ProductServiceImpl(ProductRepository repository, ProductDao productDao, ProductImgService productImgService, ProductClassService productClassService, AuthUserService authUserService, DeviceService deviceService){
super(repository);
this.productDao = productDao;
this.productImgService = productImgService;
this.productClassService = productClassService;
this.authUserService = authUserService;
this.deviceService = deviceService;
}
final
ProductDao productDao;
...
I use it in the service like this:
midResult = productDao.findAll((root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> list = new ArrayList<>();
list.add(criteriaBuilder.equal(root.get("ouId").as(Long.class),product.getOuId()));
if(product.getPclassId()!=null)
list.add(criteriaBuilder.equal(root.get("pclassId").as(Long.class),product.getPclassId()));
if(product.getProductStatus()!=null)
list.add(criteriaBuilder.equal(root.get("productStatus").as(Integer.class),product.getProductStatus()));
if(product.getProductName()!=null)
list.add(criteriaBuilder.equal(root.get("productName").as(String.class),product.getProductName()));
if(product.getCreator()!=null)
list.add(criteriaBuilder.equal(root.get("creator").as(Integer.class),product.getCreator()));
list.add(criteriaBuilder.between(root.get("createTimeTmp").as(Long.class),Long.parseLong(finalStarttsp),Long.parseLong(finalEndtsp)));
Predicate[] p = new Predicate[list.size()];
criteriaQuery.where(criteriaBuilder.and(list.toArray(p)));
return criteriaQuery.getRestriction();
}, pageable);
The Product Class definition is good .
And when I run this code , error turned out to be :
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property findAll found for type Product!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:247) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:398) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:378) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:86) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.PartTreeMybatisQuery.<init>(PartTreeMybatisQuery.java:81) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.MybatisQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(MybatisQueryLookupStrategy.java:71) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.MybatisQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(MybatisQueryLookupStrategy.java:120) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.query.MybatisQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(MybatisQueryLookupStrategy.java:50) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:436) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:221) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263) ~[spring-data-commons-1.13.6.RELEASE.jar:na]
at org.springframework.data.mybatis.repository.support.MybatisRepositoryFactoryBean.afterPropertiesSet(MybatisRepositoryFactoryBean.java:64) ~[spring-data-mybatis-1.0.17.RELEASE.jar:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.10.RELEASE.jar:4.3.10.RELEASE]
I'm using springboot and there's no config like #EnableJpaRepositories
But it don't seems to be necessary cause other repository is good .
You are using spring-data in incorrect way. When you write method findAll in repository, it will look for given attribute in entity.
For example, you have an entity User with attribute firstName. Then you can defined method like, findByFirstName.
In given example, spring-data looking for attribute all which is not available as a part of Product.
In this case, you need to write your own query using #Query annotation.
BTW, what you want to achieve?
It works like this for me:
#NonNull
Page<Product> findAll(#Nullable Specification<Product> specification, #NonNull Pageable pageable);

Mockito/Powermock not working as expected with Kotlin

I'm using mockito/powermock version 1.7.0, Spring Boot 2.0.0 M2, Kotlin 1.3.0.
I'm testing a Spring #Service class, that inject a Repository.
I want to mock that repository on my tests, so I can just test the class itself.
I'm new to Kotlin, but I come from Java, so I tried doing this "the java way", but probably I'm missing something...
Here is my Service interface:
interface MyService {
fun create(myObject: MyObject): MyObject
}
... and its implementation:
#Service
class DefaultMyService : MyService {
#Autowired
lateinit var myRepository: MyRepository
override fun create(myObject: MyObject): MyObject = this.myRepository.insert(myObject)
}
Here is my repository (I'm using Spring Data with Mongo):
interface MyRepository: MongoRepository<MyObject, String>
Here is my test class:
#RunWith(PowerMockRunner::class)
#PrepareForTest(MyService::class)
class MyServiceTest {
#Mock
lateinit var myRepository: MyRepository
#InjectMocks
lateinit var myService: MyService
#Test
fun shouldDoSomething() {
val myObject = MyObject(name = "Marco")
`when`(myRepository.insert(myObject)).thenReturn(myObject)
assertEquals(myObject.name, this.myService.create(myObject).name)
}
}
When I run this test, an exception occurs:
Exception in thread "main" java.lang.NoClassDefFoundError: org/mockito/exceptions/Reporter
at sun.reflect.GeneratedSerializationConstructorAccessor5.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at org.powermock.reflect.internal.WhiteboxImpl.newInstance(WhiteboxImpl.java:260)
at org.powermock.reflect.Whitebox.newInstance(Whitebox.java:139)
at org.powermock.api.extension.reporter.AbstractMockingFrameworkReporterFactory.getInstanceForClassLoader(AbstractMockingFrameworkReporterFactory.java:41)
at org.powermock.api.extension.reporter.AbstractMockingFrameworkReporterFactory.create(AbstractMockingFrameworkReporterFactory.java:35)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.getMockingFrameworkReporter(JUnit4TestSuiteChunkerImpl.java:140)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:119)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassNotFoundException: org.mockito.exceptions.Reporter
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:202)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass1(DeferSupportingClassLoader.java:89)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:79)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 16 more
What am I doing wrong? I think it's an issue with some configuration, but I can't understand exactly where the mistake is.
It seems like that your mockito and powermock versions are not working very well together. You have to use versions which are compatible. See the compatibility matrix of powermock https://github.com/powermock/powermock/wiki/Mockito#supported-versions
Latest compatible is Mockito: 2.8.x with PowerMock: 1.7.0

Spring Data Elasticsearch cusom repository

In my Spring Boot application I'm trying to implement a fuzzy search via Elasticsearch.
This is my ES config:
#Profile("test")
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.example.domain.repository.elasticsearch")
public class ElasticsearchTestConfig {
}
I have a repository:
#Repository
public interface ESDecisionRepository extends ElasticsearchRepository<ESDecision, String>, ESDecisionRepositoryCustom {
}
In order to be able to do a fuzzy search I have created a custom repository:
public interface ESDecisionRepositoryCustom {
public List<ESDecision> findFuzzyBySearchTerm(String searchTerm);
}
and provided a custom implementation:
#Repository
public class ESDecisionRepositoryCustomImpl implements ESDecisionRepositoryCustom {
#Autowired
protected ElasticsearchTemplate elasticsearchTemplate;
#Override
public List<ESDecision> findFuzzyBySearchTerm(String searchTerm) {
Criteria c = new Criteria("name").fuzzy(searchTerm);
return elasticsearchTemplate.queryForList(new CriteriaQuery(c), ESDecision.class);
}
}
Right now during startup my application fails with a following exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ESDecisionRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property searchTerm found for type ESDecision!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 43 common frames omitted
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property searchTerm found for type ESDecision!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243)
at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:247)
at org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:398)
at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:378)
at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:89)
at org.springframework.data.elasticsearch.repository.query.ElasticsearchPartQuery.<init>(ElasticsearchPartQuery.java:44)
at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactory$ElasticsearchQueryLookupStrategy.resolveQuery(ElasticsearchRepositoryFactory.java:119)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:436)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:221)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:277)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:263)
at org.springframework.data.elasticsearch.repository.support.ElasticsearchRepositoryFactoryBean.afterPropertiesSet(ElasticsearchRepositoryFactoryBean.java:67)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
... 53 common frames omitted
What am I doing wrong and how to fix it ?
Change your custom repository implementation class name from ESDecisionRepositoryCustomImpl to ESDecisionRepositoryImpl.
From the docs
The most important bit for the class to be found is the Impl postfix of the name on it compared to the core repository interface (see below).
There is a naming convention that has to be followed to make the custom repository implementation work. Check out the docs
Try this:
#Repository
public class ESDecisionRepositoryCustomImpl implements ESDecisionRepositoryCustom {
#Autowired
protected ElasticsearchTemplate elasticsearchTemplate;
#Override
public List<ESDecision> findFuzzyBySearchTerm(String searchTerm) {
Criteria c = new Criteria("name").fuzzy(searchTerm);
return elasticsearchTemplate.queryForList(new CriteriaQuery(c), ESDecision.class);
}
}
Hope this helps.

How do you use both Spring Data JPA and Spring Data Elasticsearch repositories on the same domain class in a Spring Boot application?

I'm trying to use both Spring Data JPA and Spring Data Elasticsearch on the same domain object but it doesn't work.
When I tried to run a simple test, I got the following exception:
org.springframework.data.mapping.PropertyReferenceException: No
property index found for type Person! at
org.springframework.data.mapping.PropertyPath.(PropertyPath.java:75)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.Part.(Part.java:76)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree$OrPart.(PartTree.java:235)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree$Predicate.(PartTree.java:353)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.query.parser.PartTree.(PartTree.java:84)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.PartTreeJpaQuery.(PartTreeJpaQuery.java:61)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:95)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:206)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:73)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.(RepositoryFactorySupport.java:408)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:206)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237)
~[spring-data-commons-1.11.0.RELEASE.jar:na] at
org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92)
~[spring-data-jpa-1.9.0.RELEASE.jar:na] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
~[spring-beans-4.2.1.RELEASE.jar:4.2.1.RELEASE] ... 43 common frames
omitted
They work when disabling either one.
The project is based on Spring Boot 1.3.0.M5.
This is a sample project reproducing the situation:
https://github.com/izeye/spring-boot-throwaway-branches/tree/data-jpa-and-elasticsearch
Repositories in Spring Data are datasource agnostic, meaning that JpaRepository and ElasticsearchRepository both roll up into Repository interface. When this is the case, then auto-configuration of Spring Boot will cause Spring Data JPA to try and configure a bean for each repository in the project that inherits any Spring Data Commons base repository.
To fix this problem you need to move your JPA repository and Elasticsearch repository to separate packages and make sure to annotate your #SpringBootApplication application class with:
#EnableJpaRepositories
#EnableElasticsearchRepositories
Then you need to specify where the repositories are for each enable annotation. This ends up looking like:
#SpringBootApplication
#EnableJpaRepositories("com.izeye.throwaway.data")
#EnableElasticsearchRepositories("com.izeye.throwaway.indexing")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Then your application will be able to disambiguate which repositories are intended for which Spring Data project.
You can use like this:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
#EnableElasticsearchRepositories(includeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
public class DataConfiguration {
...
}
Or in SpringBoot:
#SpringBootApplication
#EnableJpaRepositories(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
#EnableElasticsearchRepositories(includeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ElasticsearchCrudRepository.class))
public class MyApplication {
...
}

Resources