spring-projects / spring-data-mongodb

Provides support to increase developer productivity in Java when using MongoDB. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
https://spring.io/projects/spring-data-mongodb/
Apache License 2.0
1.62k stars 1.09k forks source link

Could not determine IsNewStrategy [DATAMONGO-1212] #2128

Closed spring-projects-issues closed 9 years ago

spring-projects-issues commented 9 years ago

Florian Geßner opened DATAMONGO-1212 and commented

With the update to version 1.7.0 I get the following exception where persisting data via Repositories/MongoTemplate. With version 1.6.2 it is working fine. In the documentation there is nothing mentioned regarding changes related to this issue.

java.lang.IllegalArgumentException: Unsupported entity org.gessnerfl.persistence.springdata.mongodb.dummy.model.DummyObject! Could not determine IsNewStrategy.
    at org.springframework.data.support.IsNewStrategyFactorySupport.getIsNewStrategy(IsNewStrategyFactorySupport.java:48)
    at org.springframework.data.auditing.IsNewAwareAuditingHandler.markAudited(IsNewAwareAuditingHandler.java:80)
    at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.onApplicationEvent(AuditingEventListener.java:54)
    at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.onApplicationEvent(AuditingEventListener.java:31)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
    at org.springframework.data.mongodb.core.MongoTemplate.maybeEmitEvent(MongoTemplate.java:1600)
    at org.springframework.data.mongodb.core.MongoTemplate.doInsert(MongoTemplate.java:789)
    at org.springframework.data.mongodb.core.MongoTemplate.insert(MongoTemplate.java:739)
    at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:76)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:414)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:399)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:371)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy34.save(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
    at org.gessnerfl.persistence.springdata.mongodb.audit.aspect.AuditAwareRepositoryAspect.onVersionEvent(AuditAwareRepositoryAspect.java:58)
    at org.gessnerfl.persistence.springdata.mongodb.audit.aspect.AuditAwareRepositoryAspect.onSaveExecuted(AuditAwareRepositoryAspect.java:45)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy38.save(Unknown Source)
    at org.gessnerfl.persistence.springdata.mongodb.audit.MongoVersionRepositoryIntegrationTest.shouldCreateNoEntryAsRepositoryIsNotVersioned(MongoVersionRepositoryIntegrationTest.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Affects: 1.7 GA (Fowler)

2 votes, 7 watchers

spring-projects-issues commented 9 years ago

Florian Geßner commented

Here some implementation details:

Configuration for testing:

Base Test Configuration

@Configuration
@ComponentScan
@PropertySource("classpath:test-mongo-config.properties")
@EnableAspectJAutoProxy(proxyTargetClass = false)
public class SpringIntegrationTestConfig {

    //Implements AuditorAware<ObjectId> for spring data auditing but also a custom interface used for similar usages
    @Bean
    public DummyEditorProvider editorProvider() {
        return new DummyEditorProvider();
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

DB Config:

public abstract class BaseMongoHistoryConfig {

    public abstract EditorProvider editorProvider();

    @Value("${spring.data.mongodb.ext.history.postfix:_hist}")
    private String historyCollectionPostfix;
    @Value("${spring.data.mongodb.ext.history.sortType:NATURAL}")
    private String historySortType;
    @Value("${spring.data.mongodb.ext.history.sortDirection:DESC}")
    private String historySortDirection;

    @Bean
    public ConfigurationParameterHolder configurationParameterHolder() {
        return new ConfigurationParameterHolder(historyCollectionPostfix, historySortType, historySortDirection);
    }

    @Bean
    public MongoEntityHistoryRepository mongoVersionRepository() {
        return new MongoEntityHistoryRepositoryBean(editorProvider(), mongoTemplate(), mongoEntityUtil(), configurationParameterHolder());
    }

    @Bean
    public MongoEntityUtil mongoEntityUtil() {
        return new MongoEntityUtil(mongoTemplate());
    }

    @Bean
    public MongoDbFactory mongoDbFactory() {
        return new SimpleMongoDbFactory(mongo(), dbname());
    }

    @Bean
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoDbFactory());
    }

    public abstract String dbname();

    public abstract MongoClient mongo();

    @Bean
    public HistoryAwareRepositoryAspect onSaveAspect() {
        return new HistoryAwareRepositoryAspect(mongoVersionRepository());
    }
}
@Configuration
@EnableMongoAuditing
@EnableMongoRepositories(basePackages = "org.gessnerfl.persistence.springdata.mongodb.dummy.repo")
public class TestMongoConfig extends BaseMongoHistoryConfig {
    private static final boolean IN_MEMORY_DB = true;
    public static final String DATABASE = "dummy";

    @Autowired
    private EditorProvider editorProvider;

    @Override
    public EditorProvider editorProvider() {
        return editorProvider;
    }

    @Override
    public String dbname() {
        return DATABASE;
    }

    @Bean
    @Override
    public MongoClient mongo() {
        if (IN_MEMORY_DB) {
            return fongo().getMongo();
        } else {
            return getLocalMongoDb();
        }
    }

    private MongoClient getLocalMongoDb() {
        try {
            MongoClient mongoClient = new MongoClient("localhost", 27017);
            return mongoClient;
        } catch (UnknownHostException e) {
            throw new IllegalStateException("Cannot connect to mongodb");
        }
    }

    @Bean
    public Fongo fongo() {
        return new Fongo("InMemoryMongo");
    }
}

Domain classes for testing:

@Document
public class DummyObject implements Serializable {
    @Id
    private ObjectId id;
    @CreatedBy
    private ObjectId createdBy;
    @CreatedDate
    private Date creaetdOn;
    @LastModifiedBy
    private ObjectId modifiedBy;
    @LastModifiedDate
    private Date modifiedOn;
    private String name;
    private DummyItem dummyItem;
    private List<DummyItem> dummyItems = new ArrayList<>();
    ...
    //Getter and setter
    ...
}
public class DummyItem {
    private String name;
    ...
    //Getter and setter
    ...
}
spring-projects-issues commented 9 years ago

José Carlos Valero Sánchez commented

It is also happening to me on 1.7.0. It seems to appear when Audit is enabled. The bug disappears when I disable auditing capabilities.

Additionally, I am also using aspectJ. I can see from your traces aspectJ is also been used

spring-projects-issues commented 9 years ago

Oliver Drotbohm commented

Have you tried extending AbstractMongoConfiguration for the MongoDB specific parts of your configuration? It sets up a Spring bean for a MongoMappingContext and pre-populates it with all classes annotated with @Document underneath the package of that configuration class. The package to scan can be customized by overriding getMappingBasePackage().

This will make sure the entity metadata is available after bootstrap

spring-projects-issues commented 9 years ago

Florian Geßner commented

using AbstractMongoConfiguration helped me to fix the issue. Thanks for your help

spring-projects-issues commented 9 years ago

José Carlos Valero Sánchez commented

Ohh Oliver, it works now!

Thank you very much, not only for the "recipe" but particularly for taking the effort of sharing the in-depth reason of it.

Very much appreciated

spring-projects-issues commented 9 years ago

Emircan Arıkök commented

If you are using java conf, below way could work but how to do in XML ? . Anyone know how to do it ? My xml configuration is like that.

<mongo:db-factory uri="**" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    </bean>

    <mongo:repositories base-package="com.marl.data.repository" >
    </mongo:repositories>

    <mongo:auditing></mongo:auditing>
spring-projects-issues commented 9 years ago

Paolo commented

there is no way to fix issue if i set a different id on mapping-converter element...but all work with default id="mappingConverter"

spring-projects-issues commented 9 years ago

Paolo commented

Sorry for reopen...the problem is that mongo:auditing point to default mapping-context...so simply add this...

\

...and all work.

Can close, and sorry again, but documentation is not so clear