4

I am trying to add a custom implementation (FruitRepositoryCustomImpl) for a JPA repository (FruitRepository). Here is my code -

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.*;

import javax.persistence.*;

interface FruitRepository extends JpaRepository<Fruit, Long>, FruitRepositoryCustom {

}

interface FruitRepositoryCustom {
    void detachItem(Fruit fruit);
}

@Repository
class FruitRepositoryCustomImpl implements FruitRepositoryCustom {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void detachItem(Fruit fruit) {
        entityManager.detach(fruit);
    }

}

@SpringBootApplication
public class EatFruitApplication {

    public static void main(String[] args) {
        SpringApplication.run(EatFruitApplication.class, args);
    }
}

and Entity

@Entity
class Fruit {
    @Id
    @GeneratedValue
    private Long id;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

as well as

@RestController
@RequestMapping("/fruits")
class FruitRestController {
    @Autowired
    private FruitRepository fruitRepository;

    @RequestMapping(value = "/{fruitId}", method = RequestMethod.GET)
    public Fruit readItem(@PathVariable Long fruitId) {
        Fruit fruit = this.fruitRepository.findOne(fruitId);
        return fruit;
    }

    @RequestMapping(method = RequestMethod.POST)
    public Fruit addItem(@RequestBody Fruit fruit) {
        fruitRepository.save(fruit);
        return fruit;
    }
}

But I am getting following error while running the application.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fruitRestController': Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private eat.fruit.FruitRepository eat.fruit.FruitRestController.fruitRepository; 
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fruitRepository': Invocation of init method failed; 
nested exception is org.springframework.data.mapping.PropertyReferenceException: No property detachItem found for type Fruit!   at 
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at 
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at 
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at 
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]  at 
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]    at 
org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]    at 
org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]    at 
org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]   at 
org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]   at 
eat.fruit.EatFruitApplication.main(EatFruitApplication.java:36) [classes/:na]   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]   at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]    at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]    at 
java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]     at 
com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na] Caused by: 
org.springframework.beans.factory.BeanCreationException: Could not autowire field: private eat.fruit.FruitRepository 
eat.fruit.FruitRestController.fruitRepository; nested exception is 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fruitRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property detachItem found for type Fruit!   at 
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at 
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  ... 22 common frames omitted 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fruitRepository': Invocation of init method failed; nested exception is 
org.springframework.data.mapping.PropertyReferenceException: No property detachItem found for type Fruit!   at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at 
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at 
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]     at 
org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   at 
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]  at 
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at 
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   ... 24 common frames omitted 
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property detachItem found for type Fruit!    at 
org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:329) ~[spring-data-commons-1.11.4.RELEASE.jar:na]    at 
org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:309) ~[spring-data-commons-1.11.4.RELEASE.jar:na]    at 
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:272) ~[spring-data-commons-1.11.4.RELEASE.jar:na]  at 
org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:243) ~[spring-data-commons-1.11.4.RELEASE.jar:na]  at 
org.springframework.data.repository.query.parser.Part.<init>(Part.java:76) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:235) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.repository.query.parser.PartTree$Predicate.buildTree(PartTree.java:373) ~[spring-data-commons-1.11.4.RELEASE.jar:na]   at 
org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:353) ~[spring-data-commons-1.11.4.RELEASE.jar:na]  at 
org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:84) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:62) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]     at 
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:100) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]    at 
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:211) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]  at 
org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:74) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]   at 
org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:416) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:206) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn(RepositoryFactoryBeanSupport.java:251) ~[spring-data-commons-1.11.4.RELEASE.jar:na]     at 
org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:237) ~[spring-data-commons-1.11.4.RELEASE.jar:na]    at 
org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:92) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]   at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]    at 
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]   ... 34 common frames omitted

Please help.

Thanks.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Moazzam Khan
  • 3,130
  • 2
  • 20
  • 35
  • the stack trace for that exception would tell you where it originates ... SpringDataJPA API most likely (as opposed to JPA API) – Neil Stockton Jun 26 '16 at 10:05
  • @NeilStockton it originates from spring code, where it is trying to find `detachItem` property for `Fruit` class. I am not able to find why it is trying to do that. – Moazzam Khan Jun 26 '16 at 10:12
  • @NeilStockton Added stacktrace. – Moazzam Khan Jun 26 '16 at 10:19
  • Any possibility that spring boot is trying to autoconfigure the custom interface behind the scenes based on method name? Try changing void detachItem(Fruit fruit); to void detachFruit(Fruit fruit); – Martin McKeaveney Jun 26 '16 at 10:23
  • @MartinMcKeaveney Getting same error after changing `detachItem` to `detachFruit` – Moazzam Khan Jun 26 '16 at 10:28
  • why not work out WHAT JPQL it is trying to execute there? There is some JpaQuery in the trace ... so what is the JPQL? – Neil Stockton Jun 26 '16 at 10:37
  • @NeilStockton It looks like spring is trying to resolve `detachItem` as queries like if we define something like `findByName` in `FruitRepository`? – Moazzam Khan Jun 26 '16 at 10:49
  • You've probably found the answer already, if not, it's here: https://stackoverflow.com/questions/20777785/org-springframework-data-mapping-propertyreferenceexception-no-property-catch-f – Alejandro Raiczyk Nov 30 '17 at 11:20

1 Answers1

0

Spring's handling of the @PersistenceContext annotation does almost exactly what you're after, with one big difference: you always get a transaction scoped EntityManager and Spring injects always the same instance for the same thread, so you have kind of propagation and don't have to worry about thread-safety. But you'll never get an extended context this way! Believe me, Spring 3 and extended persistence context don't play well together, maybe this will change in Spring 3.1 but I'm afraid that's not in their focus. If you want to use an extended persistence context let Spring inject the EntityManagerFactory (via @PersistenceUnit annotation) and then create the EntityManager on your own. For propagation you'll have to either pass the instance as a parameter or store it in a ThreadLocal yourself.

try reading this link: http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

Example you can go through

 public class SomeClient {

      @Autowired
      private PersonRepository repository;

      public void doSomething() {
        List<Person> persons = repository.findByLastname("Matthews");
      }
    }
Deepanjan
  • 649
  • 2
  • 8
  • 15
  • I am using Spring 4. I am sorry for I could not understand your answer very well since I am new to spring. Could you provide any links from where I can understand how to do it in a right way? – Moazzam Khan Jun 26 '16 at 10:03
  • Ok fine. You can do one more thing instead of using@PersistenceContext you can autowire the repository using@Autowired and can use the function available in JpaRepository to transact with db. Jpa provides all privileges to do operation on db. – Deepanjan Jun 26 '16 at 10:18
  • Thanks. I already have been following `1.3 Custom implementations for Spring Data repositories` from the link you have provided. The code you have provided is like a wrapper over repository. If we can add custom functions using custom implementation of repository, why we should do something different? – Moazzam Khan Jun 26 '16 at 10:32
  • You can also add custom implementation using jpa repository within the interface . I hope i am able to help you somewhere. – Deepanjan Jun 26 '16 at 10:51