Akhil Prajapati
Akhil Prajapati

Reputation: 1281

Spring Data JPA findById() throwing ClassCastException

I have a method that is using findById() method of Spring Data JPA. However, this method is returning ClassCastException on line number 1 of the getSupportedKey() method where I am calling findById():

MySupportedKey cannot be cast to java.util.Optional

private MySupportedKey getSupportedKey(String tenant, String key) {
        Optional<MySupportedKey> mySupportedKeyOptional = mySupportedKeyRepository.findById(new MySupportedKeyId(tenant, key));
        MySupportedKey mySupportedKey= null;
        if(mySupportedKeyOptional !=null) {
             mySupportedKey= mySupportedKeyOptional.orElse(null);
        }
        return mySupportedKey;
    }

I have been beating my head for a long time but I am not getting anything. Please help me in getting this resolved. I am using spring-data-jpa: 2.0.8.RELEASE.

Adding the Repository Source Code:

public interface MySupportedKeyRepository extends JpaRepository<MySupportedKey, MySupportedKeyId> {

List<MySupportedKey> findByIdTenant(@NotNull String tenant);
}

Adding the complete stack trace of error:

java.lang.ClassCastException: com.test.service.user.entity.MySupportedKey cannot be cast to java.util.Optional
at com.test.service.user.repository.MySupportedKeyRepository$MockitoMock$1304362870.findById(Unknown Source)
at com.test.service.user.repository.MySupportedKeyRepository$MockitoMock$1304362870.findById(Unknown Source)
at com.test.service.user.userpreferences.PreferencesServiceImpl.getSupportedKey(PreferencesServiceImpl.java:217)
at com.test.service.user.userpreferences.PreferencesServiceImpl.updateUserPreferences(PreferencesServiceImpl.java:167)
at com.test.service.user.userpreferences.PreferencesServiceImpl.lambda$2(PreferencesServiceImpl.java:92)
at java.util.ArrayList.forEach(Unknown Source)
at com.test.service.user.userpreferences.PreferencesServiceImpl.updateUserPreferences(PreferencesServiceImpl.java:92)
at com.test.service.user.preferences.PreferencesServiceImplTest.updateUserPreferences(PreferencesServiceImplTest.java:300)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.mockito.internal.junit.JUnitRule$1.evaluateSafely(JUnitRule.java:52)
at org.mockito.internal.junit.JUnitRule$1.evaluate(JUnitRule.java:43)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.RunPrepareTestInstanceCallbacks.evaluate(RunPrepareTestInstanceCallbacks.java:64)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.springframework.test.context.junit4.statements.SpringFailOnTimeout.evaluate(SpringFailOnTimeout.java:87)
at org.springframework.test.context.junit4.statements.ProfileValueChecker.evaluate(ProfileValueChecker.java:103)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.springframework.test.context.junit4.statements.ProfileValueChecker.evaluate(ProfileValueChecker.java:103)
at org.springframework.test.context.junit4.rules.SpringClassRule$TestContextManagerCacheEvictor.evaluate(SpringClassRule.java:230)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

Upvotes: 1

Views: 2348

Answers (3)

jingle123
jingle123

Reputation: 83

Cannot add comment, just wanted to elaborate on Jens answer since it took me a while to figure out how to fix this (being a newbie). To fix the issue I changed my code from:

when(mongoRepository.findById(Mockito.anyString())).thenAnswer(new Answer<MongoObj>() {
        @Override
        public MongoObj answer(InvocationOnMock invocation) throws Throwable {
            MongoObj repush = new MongoObj();
            //Some other code

            return repush;
        }
    });

To

when(mongoRepository.findById(Mockito.anyString())).thenAnswer(new Answer<Optional<MongoObj>>() {
        @Override
        public Optional<MongoObj> answer(InvocationOnMock invocation) throws Throwable {
            MongoObj repush = new MongoObj();
            //Some other code

            return Optional.of(repush);
        }
    });

Hope this helps!

Upvotes: 0

Rizwan
Rizwan

Reputation: 2437

Modify the Optional handling in your below method to get the correct representation like below:

private MySupportedKey getSupportedKey(String tenant, String key) {
            Optional<MySupportedKey> mySupportedKeyOptional = mySupportedKeyRepository.findById(new MySupportedKeyId(tenant, key));
            MySupportedKey mySupportedKey= null;
            if(mySupportedKeyOptional.isPresent()) {
                 mySupportedKey= mySupportedKeyOptional.get();
            }
            return mySupportedKey;
        }

Upvotes: 0

Jens Schauder
Jens Schauder

Reputation: 81907

You set up a Mockito mock for the repository and probably told it to return a MySupportedKey instance when findById gets called. But since findById is supposed to return an Optional you now get the exception.

You can see that this is coming from Mockito in the very first two lines of the stack trace.

java.lang.ClassCastException: com.test.service.user.entity.MySupportedKey cannot be cast to java.util.Optional
at com.test.service.user.repository.MySupportedKeyRepository$MockitoMock$1304362870.findById(Unknown Source)

Upvotes: 4

Related Questions