Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot subclass final class com.sun.proxy.$Proxy202 #793

Closed
spring-projects-issues opened this issue May 7, 2019 · 2 comments
Closed

Cannot subclass final class com.sun.proxy.$Proxy202 #793

spring-projects-issues opened this issue May 7, 2019 · 2 comments
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

FrostbittenKing opened BATCH-2821 and commented

I fail to correctly use the RepositoryMethodReference with the RepositoryItemReaderBuilder.

After I found your sample tests (they are only unit tests), i tried it in an actual spring boot batch application, but the application always terminates on startup, when it tries to instantiate the bean for.

 

-- Snip
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.data.RepositoryItemReader]: Factory method 'reader' threw exception; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class com.sun.proxy.$Proxy202Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.data.RepositoryItemReader]: Factory method 'reader' threw exception; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class com.sun.proxy.$Proxy202 at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:583) ... 64 common frames omittedCaused by: java.lang.IllegalArgumentException: Cannot subclass final class com.sun.proxy.$Proxy202 at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:565) at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329) at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91) at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:305) at org.springframework.batch.item.data.builder.RepositoryItemReaderBuilder$RepositoryMethodReference.methodIs(RepositoryItemReaderBuilder.java:270) at sample.batch.jobs.SampleJob.reader(SampleJob.java:124) at sample.batch.jobs.SampleJob$$EnhancerBySpringCGLIB$$879fb0c0.CGLIB$reader$4(<generated>) at sample.batch.jobs.SampleJob$$EnhancerBySpringCGLIB$$879fb0c0$$FastClassBySpringCGLIB$$f29d5ef8.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:365) at sample.batch.jobs.SampleJob$$EnhancerBySpringCGLIB$$879fb0c0.reader(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 65 common frames omitted

Sorry, cannot list the complete stacktrace (work-related).

I'm not sure how this is supposed to work, since the class gets proxied (and as documented) cannot be final, but this is a Repository Interface extending JpaRepository, which makes it final by design, as far as I understand.

I'm sorry for asking but was this ever tested outside a unit test?

 

Following sample fails, and blows up with a stacktrace similar to the one listed above:

@Repository
public interface SampleRepository extends JpaRepository<JpaSample,Long>
{
// ...
}

public class SampleReaderIT extends AbstractIntegrationTest // common base class for spring full blown integration tests
{
     @Test
     public void sampleTest() throws Exception
     {
         RepositoryItemReaderBuilder.RepositoryMethodReference<SampleRepository> methodReference =
            new RepositoryItemReaderBuilder.RepositoryMethodReference<>(sampleRepository);        methodReference.methodIs().getOne(null);        new RepositoryItemReaderBuilder<JpaSample>()
            .repository(methodReference)
            .pageSize(100)
            .saveState(false)
            .sorts(MapUtils.putAll(new HashMap<>(), new Object[][]`"id", Sort.Direction.ASC`))
            .build();
     }
}

No further details from BATCH-2821

@spring-projects-issues spring-projects-issues added type: bug status: waiting-for-triage Issues that we did not analyse yet labels Dec 16, 2019
@ghost
Copy link

ghost commented Apr 12, 2021

The problem is in the method RepositoryItemReaderBuilder.RepositoryMethodReference#methodIs:

public T methodIs() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.repository.getClass());
enhancer.setCallback(this.repositoryInvocationHandler);
return (T) enhancer.create();
}

The enhancer.create() call fails with an error:

java.lang.IllegalArgumentException: Cannot subclass final class com.sun.proxy.$Proxy202

because the actual repository object is proxied.

How could we fix this?

Could we use ClassUtils.getUserClass(Class) or AopUtils.getTargetClass(Object) in RepositoryMethodReference in order to determine the real repository class declared by user and then create an Enhancer for it?

Another solution would be to pass the repository's Class as a constructor argument into RepositoryMethodReference.

@00010001
Copy link

00010001 commented May 2, 2022

@fmbenhassine fmbenhassine added in: infrastructure has: votes Issues that have votes for: backport-to-4.3.x Issues that will be back-ported to the 4.3.x line and removed status: waiting-for-triage Issues that we did not analyse yet labels May 2, 2022
@fmbenhassine fmbenhassine added this to the 5.0.0-M3 milestone May 2, 2022
@fmbenhassine fmbenhassine changed the title Cannot subclass final class com.sun.proxy.$Proxy202 [BATCH-2821] Cannot subclass final class com.sun.proxy.$Proxy202 May 17, 2022
fmbenhassine added a commit to fmbenhassine/spring-batch that referenced this issue May 17, 2022
This class and its usage are confusing and causing
context startup failures.

This commit removes that class to simplify the creation
of a  RepositoryItemReader through its builder.

Issue spring-projects#793
@fmbenhassine fmbenhassine modified the milestones: 5.0.0-M3, 5.0.0-M4 May 17, 2022
@fmbenhassine fmbenhassine removed the for: backport-to-4.3.x Issues that will be back-ported to the 4.3.x line label May 17, 2022
fmbenhassine added a commit to fmbenhassine/spring-batch that referenced this issue May 24, 2022
This class and its usage have been reported to be confusing and
causing context startup failures without real added value.

This commit removes that class to simplify the creation
of a RepositoryItemReader through its builder.

Issue spring-projects#793
fmbenhassine added a commit that referenced this issue Jul 18, 2022
This class and its usage have been reported to be confusing and
causing context startup failures without real added value.

This commit removes that class to simplify the creation
of a RepositoryItemReader through its builder.

Resolves #793
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants