1

I'm new to spring framework and I'm trying to start from the simple application for my friends which will collect gossips about our company.

The problem that I'm unable to inject persistence repository into service layer.

Here is the only class into domain (Gossip.java):

package ru.gossips.core.domain;

public class Gossip {
    private Long id;
    private String text;

    public Gossip() {
    }

    public Gossip(Long id, String text) {
        this.id = id;
        this.text = text;
    }

    ... getters and setters omitted
}

Here is his sibling class in the persistence layer (PGossip.java):

package ru.gossips.persistence.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class PGossip {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String text;

    protected PGossip() {
    }

    public PGossip(String author, String text) {
        this.text = text;
    }

    ... getters and setters omitted

    @Override
    public String toString() {
        return String.format(
                "Persistence: Gossip[id=%d, text='%s']",
                id, text);
    }
}

I also have a repository for gossips:

package ru.gossips.persistence.repository;

import org.springframework.data.repository.CrudRepository;
import ru.gossips.persistence.domain.PGossip;

public interface GossipRepository extends CrudRepository<PGossip, Long> {
}

... and a gossip service:

package ru.gossips.core.services;

import ru.gossips.core.domain.Gossip;

import java.util.List;

public interface GossipService {
    List<Gossip> requestAllGossips();
}

and it's implementation:

package ru.gossips.core.services;

import org.springframework.beans.factory.annotation.Autowired;
import ru.gossips.core.domain.Gossip;
import ru.gossips.persistence.repository.GossipRepository;
import ru.gossips.persistence.domain.PGossip;

import java.util.ArrayList;
import java.util.List;

public class GossipServiceImpl implements GossipService {
    // PROBLEM HERE!!!!
    @Autowired                               
    private GossipRepository gossipRepository;

    @Override
    public List<Gossip> requestAllGossips() {

        // converting all persistence gossips to domain gossips
        final List<Gossip> gossipList = new ArrayList<Gossip>();
        for (PGossip pGossip : gossipRepository.findAll()) {
            gossipList.add(new Gossip(pGossip.getId(), pGossip.getText()));
        }

        return gossipList;
    }
}

And here I recieve the warning from IntelliJ IDEA: Autowired members must be defined in the valid spring bean.

However, I've done all that need to be done according to Spring Data Jpda Reference v 1.4.3:

  1. Declare an interface extending Repository or one of its subinterfaces and type it to the domain class that it will handle - done
  2. Declare query methods on the interface - I use only the metods provided by CrudRepository
  3. Set up Spring to create proxy instances for those interfaces - the most difficult step. Since I use Java Configuration instead of xml configuration, I've created Persitence config (see below)
  4. Get the repository instance injected and use it - here I get the warning.

My persistence config:

package ru.gossips.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.H2;

@Configuration
@EnableJpaRepositories(basePackages = "ru.gossips.persistence.repository")
@EnableTransactionManagement
public class PersistenceConfig {
    @Bean
    public DataSource dataSource() {
        //todo: how to make non-embedded database?
        return new EmbeddedDatabaseBuilder().setType(H2).build();
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(false);
        hibernateJpaVendorAdapter.setGenerateDdl(true);
        hibernateJpaVendorAdapter.setDatabase(Database.H2);
        return hibernateJpaVendorAdapter;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new JpaTransactionManager();
    }

    @Bean
    public EntityManagerFactory entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

        factory.setJpaVendorAdapter(jpaVendorAdapter());
        factory.setDataSource(dataSource());

        factory.setPackagesToScan("ru.gossips.persistence.domain");
        factory.afterPropertiesSet();

        return factory.getObject();
    }
}

I also have WebApplicationInitializer with PersistenceConfig mentioned in getRootConfigClasses(), also have CoreConfig and DomainConfig. However, after spending about a week trying to understand what's going wrong I can't get out of the strong feeling that I've missed some really stupid mistake in my configuration/code.

What could be wrong?

Thanks in advance!

Added: CoreConfig.java:

package ru.gossips.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.gossips.core.services.GossipService;
import ru.gossips.core.services.GossipServiceImpl;

@Configuration
public class CoreConfig {

    @Bean
    public GossipService gossipService() {
        return new GossipServiceImpl();
    }
}

Added: Here is the actual stack trace I get while deploying app:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.gossips.persistence.repository.GossipRepository ru.gossips.core.services.GossipServiceImpl.gossipRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:381)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1558)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:620)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:567)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1487)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:97)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1328)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1420)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:848)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private ru.gossips.persistence.repository.GossipRepository ru.gossips.core.services.GossipServiceImpl.gossipRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    ... 56 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gossipRepository': Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1014)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:957)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 58 more
Caused by: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:142)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.setBeanFactory(PersistenceExceptionTranslationInterceptor.java:118)
    at org.springframework.data.repository.core.support.PersistenceExceptionTranslationRepositoryProxyPostProcessor.<init>(PersistenceExceptionTranslationRepositoryProxyPostProcessor.java:44)
    at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.setBeanFactory(TransactionalRepositoryFactoryBeanSupport.java:85)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1572)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1540)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    ... 67 more

THE SOLUTION:

Big thanks @RC for the solution.

Short solution: add this bean to your config:

@Bean
public HibernateExceptionTranslator hibernateExceptionTranslator(){
    return new HibernateExceptionTranslator();
}

And solution explained: link

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
ivstas
  • 1,203
  • 1
  • 16
  • 31
  • 2
    How are you telling Spring about the `GossipServiceImpl` class? You would usually have either an `@Component` or `@Service` (right now, completely equivalent) annotation on `GossipServiceImpl`. I don't see anywhere that you're explicitly telling Spring to create a `GossipServiceImpl` bean, and IntelliJ may be figuring that out and warning you. – chrylis -cautiouslyoptimistic- Jan 20 '14 at 20:20
  • @chrylis I have this bean registered in CoreConfig (just added the code to message). After that I inject `GossipServiceImpl` into web layer. However, my problem is `GossipRepository`, not the `GossipServiceImpl`. – ivstas Jan 20 '14 at 20:32
  • Does it run? It's possible IntelliJ just can't figure out the impl for your persistence repo. – Taylor Jan 20 '14 at 20:34
  • 1
    Nevermind IntelliJ.. what is the actual stacktrace show? – Adam Gent Jan 20 '14 at 20:34
  • 3
    http://stackoverflow.com/questions/8434712/no-persistence-exception-translators-found-in-bean-factory-cannot-perform-excep probably –  Jan 20 '14 at 20:39
  • We need exact error or warning messages, then. "Here" needs to be specific. – chrylis -cautiouslyoptimistic- Jan 20 '14 at 20:39
  • @AdamGent I don't really care about idea's output, but unfortunatelly I also get errors while deploying. I added the stack trace. – ivstas Jan 20 '14 at 20:40
  • @RC is right, the issue is covered there. – Taylor Jan 20 '14 at 20:42
  • @RC, thanks a lot, you saved me! As a spring newbie, I don't really understand how does it works, but adding `HibernateExceptionTranslator` solves the problem. – ivstas Jan 20 '14 at 20:45
  • 1
    @Kite, bit of friendly advice, just try googling the exception next time. :) – Taylor Jan 20 '14 at 20:53

1 Answers1

0

Add @Repository over interface GossipRepository as it will mark it as a repository bean in the spring framework and will be taken care by spring container.

Also add @Component over the service class and interface e.g. in your problem GossipService and GossipServiceImpl to register the classes with spring container

Sahil Bhalla
  • 175
  • 1
  • 4