VerifierMappingExceptions с Spring Boot 1.3.1 при использовании Spring Data JPA и Spring Data Cassandra

Я использую Spring-boot-starter-parent, позволяя Spring управлять всеми зависимостями для моего проекта, и с этим я использую Spring Data Cassandra и Spring data JPA

Версия Spring-boot-starter-parent была 1.2.8.RELEASE. Недавно я обновил версию до 1.3.1.RELEASE и начал сталкиваться со странной проблемой с Spring Data Cassandra.

 21:23:21.783 [localhost-startStop-1] WARN  org.apache.catalina.loader.WebappClassLoaderBase   - Failed to check for ThreadLocal references for web application [ROOT]
java.lang.UnsupportedOperationException: null
    at com.zaxxer.hikari.util.FastList.iterator(FastList.java:209) ~[HikariCP-2.4.3.jar:na]
    at org.apache.catalina.loader.WebappClassLoaderBase.loadedByThisOrChild(WebappClassLoaderBase.java:2195) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks(WebappClassLoaderBase.java:2105) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalsForLeaks(WebappClassLoaderBase.java:2060) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.loader.WebappClassLoaderBase.clearReferences(WebappClassLoaderBase.java:1575) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.loader.WebappClassLoaderBase.stop(WebappClassLoaderBase.java:1521) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.loader.WebappLoader.stopInternal(WebappLoader.java:447) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5517) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:232) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1424) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at org.apache.catalina.core.ContainerBase$StopChild.call(ContainerBase.java:1413) [tomcat-embed-core-8.0.30.jar:8.0.30]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_72]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_72]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_72]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_72]
21:23:21.791 [main] ERROR org.springframework.boot.SpringApplication         - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.service.intf.UserService com.sarvint.rest.UserController.uService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.repositories.UserRepository com.sarvint.service.UserServiceImpl.userRepo; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.sarvint.domain.User:
Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:764) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
    at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:357) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:305) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1124) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1113) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE]
    at com.sarvint.Application.main(Application.java:18) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.service.intf.UserService com.sarvint.rest.UserController.uService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.repositories.UserRepository com.sarvint.service.UserServiceImpl.userRepo; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.sarvint.domain.User:
Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation

    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ... 17 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.sarvint.repositories.UserRepository com.sarvint.service.UserServiceImpl.userRepo; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is org.springframework.data.cassandra.mapping.VerifierMappingExceptions: com.sarvint.domain.User:
Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation

В нем говорится, что я должен аннотировать Entities с помощью @Table и т. Д., Но эти объекты относятся к данным Spring. JPA Entities, которые имеют данные Spring Cassandra, которые я аннотировал с помощью @Table и т. Д.

Старт-класс:

@SpringBootApplication
@EnableJpaRepositories( repositoryFactoryBeanClass =    GenericRepositoryFactoryBean.class )
@EntityScan("com.sarvint.domain")
@Import(CassandraConfig.class)
public class Application {

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

}

Конфигурация Spring Data JPA:

@Configuration
@ComponentScan( basePackages = "com.sarvint" )
@PropertySource( value = { "classpath:application.properties" } )
public class AppConfig extends WebMvcConfigurerAdapter {

@Autowired
private Environment environment;

                                                                                                                                                                                                                                            @Override
public void configureDefaultServletHandling( DefaultServletHandlerConfigurer configurer )
{
    configurer.enable();
}

@Bean
public DataSource dataSource()
{
    HikariConfig config = new HikariConfig();
    int poolSize = 20;
    config.setMaximumPoolSize(poolSize);
    config.setDataSourceClassName(environment.getRequiredProperty("spring.datasource.driver-class-name"));
    config.addDataSourceProperty("url", environment.getRequiredProperty("spring.datasource.url"));
    config.addDataSourceProperty("user", environment.getRequiredProperty("spring.datasource.username"));
    config.addDataSourceProperty("password", environment.getRequiredProperty("spring.datasource.password"));
    return new HikariDataSource(config);
}

Сущность Spring Data JPA:

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

@Entity
@Table( name = "user" )

public class User implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
@Column( name = "u_id" )
private Integer userId;

@Column( name = "u_first_name" )
private String firstName;

@Column( name = "u_last_name" )
private String lastName;
}

Теперь перейдем к конфигурации Spring Data Cassandra:

    package com.sarvint.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;

@Configuration
@PropertySource(value = { "classpath:cassandra.properties" })
@EnableCassandraRepositories(basePackages="com.sarvint.cassandra.domain")
public class CassandraConfig extends AbstractCassandraConfiguration {

    private static final Logger LOG = LoggerFactory.getLogger(CassandraConfig.class);


    @Autowired
    private Environment environment;

    @Bean
    public CassandraClusterFactoryBean cluster() {
        LOG.info("INSIDE cluster()");
        CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
        cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
        cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
        return cluster;
    }

    @Override
    protected String getKeyspaceName() {
        LOG.info("INSIDE getting keyspace name");
        return environment.getProperty("cassandra.keyspace");
    }

    @Bean
    public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
        LOG.info("INSIDE cassandra mapping");
        return new BasicCassandraMappingContext();
    }
}

Сущность Spring Cassandra:

import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;

@Table( value = "biometric_param" )
public class BiometricParam {

    @PrimaryKeyColumn(name="user_id",ordinal=0,type=PrimaryKeyType.PARTITIONED)
    private Integer userId;

    @PrimaryKeyColumn(name="workout_uuid",ordinal=1,type=PrimaryKeyType.PARTITIONED)
    private String workoutUUID;

    @PrimaryKeyColumn(name="bio_param_key",ordinal=2,type=PrimaryKeyType.CLUSTERED)
    private String bioParamKey;

    @Column(value="bio_param_val")
    private Float bioParamValue;
}

Cassandra.properties

cassandra.contactpoints=127.0.0.1
cassandra.port=9042
cassandra.keyspace=test

Спасибо за любую помощь!


person Shreesha N    schedule 08.03.2016    source источник


Ответы (2)


В чем проблема?

Это ошибка в Spring Data Cassandra. У вас есть несколько модулей Spring Data на вашем пути к классу. В таком случае Spring Data пытается выяснить, к какому модулю принадлежит конкретный репозиторий. Spring Data Cassandra упускает возможность идентифицировать вашу сущность JPA User принадлежит не Cassandra, поэтому Spring Data Cassandra пытается создать экземпляр репозитория для вашего UserRepository.

Вы увидите несколько DEBUG сообщений журнала о том, что Spring Data входит в режим строгой конфигурации, если вы включите DEBUG ведение журнала.

Почему эта ошибка возникает сейчас, а не в более ранней версии Spring Boot?

Spring Boot 1.3.0 представил автоконфигурацию для репозиториев Spring Data Cassandra. Из-за этого изменения Spring Boot выполняет сканировать репозитории Spring Data Cassandra, как вы настроили его только с @EnableCassandraRepositories.

Только комбинация EnableCassandraRepositories по умолчанию с использованием нескольких модулей Spring Data выявляет эту ошибку.

И что теперь?

Установите spring.data.cassandra.repositories.enabled=false в своем application.properties, чтобы отключить автоконфигурацию, поскольку вы сами используете @EnableCassandraRepositories(basePackages="com.sarvint.cassandra.domain").

Я создал отчет об ошибке здесь, чтобы вы могли отслеживать прогресс, если хотите.

person mp911de    schedule 10.03.2016
comment
Если я добавлю spring.data.cassandra.repositories.enabled=false в application.properties, он говорит, что нет конструктора для класса Repository, который связан с данными Spring JPA - person Shreesha N; 11.03.2016
comment
Отлично, значит, вы избавились от проблемы с Кассандрой. Далее идет JPA, поэтому создайте новый пост, содержащий другую трассировку стека. - person mp911de; 11.03.2016
comment
Я собирался задать тот же вопрос Кассандре и Neo4J. Не то что в этом, у меня изначально нет репозиториев neo4j. Но это дало мне ту же ошибку, что и для кассандры. Затем я установил spring.data.neo4j.repositories.enabled = false, и он начал нормально работать. Спасибо @ mp911de за эту информацию. Похоже, та же ошибка есть и с spring neo4j. - person Hareendra Chamara Philips; 14.05.2017

Попробуйте перейти на HikariCP 2.4.4. Он содержит это исправление:

issue 495: implemented iterator() method on custom FastList to support Tomcat memory leak detection.

person brettw    schedule 09.03.2016
comment
Это устранило проблему с FastList, HikariCp, но не реальный конфликт модуля данных Spring! В любом случае, спасибо - person Shreesha N; 11.03.2016