Search code examples
quarkusquarkus-panache

Quarkus extension using a repository based on PanacheMongoRepository


I'm currently working on a Quarkus extension which is basically a filter that is using a PanacheMongoRepository. Here is a code snippet (this is in the runtime part of the extension) :

@Provider
@Priority(Priorities.AUTHORIZATION)
@AuthorizationSecured
public class AuthorizationFilter implements ContainerRequestFilter {

    // Some injection here
     
    @Inject
    UserRepository userRepository;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // Some business logic here...

        UserEntity userEntity = userRepository.findByName(name);
        
        // Some business logic here...
    }
    
}

The repository :

@ApplicationScoped
public class UserRepository implements PanacheMongoRepository<UserEntity> {

    public UserEntity findByName(String name) {
        return find("some query...", name).firstResult();
    }

}

When the repository is called, I get the following exception:

org.jboss.resteasy.spi.UnhandledException: java.lang.IllegalStateException: This method is normally automatically overridden in subclasses...

java.lang.IllegalStateException: This method is normally automatically overridden in subclasses\n\tat io.quarkus.mongodb.panache.common.runtime.MongoOperations.implementationInjectionMissing(MongoOperations.java:765)\n\tat io.quarkus.mongodb.panache.PanacheMongoRepositoryBase.find(PanacheMongoRepositoryBase.java:119)

The processor

class AuthorizeProcessor {

    private static final String FEATURE = "authorize";

    @BuildStep
    FeatureBuildItem feature() {
        return new FeatureBuildItem(FEATURE);
    }

    @BuildStep(onlyIf = IsAuthorizeEnabled.class)
    void registerAuthorizeFilter(
            BuildProducer<AdditionalBeanBuildItem> additionalBeanProducer,
            BuildProducer<ResteasyJaxrsProviderBuildItem> resteasyJaxrsProviderProducer
    ) {
        additionalBeanProducer.produce(new AdditionalBeanBuildItem(UserRepository.class));
        additionalBeanProducer.produce(new AdditionalBeanBuildItem(AuthorizationFilter.class));
        resteasyJaxrsProviderProducer.produce(new ResteasyJaxrsProviderBuildItem(AuthorizationFilter.class.getName()));
    }
}

Any idea ?

Thanks for your help :)


Solution

  • MongoDB with Panache (and the same for Hibernate with Panache) uses bytecode enhancement at build time. When this enhancement didn't occurs it leads to the exception you mentionned at runtime: java.lang.IllegalStateException: This method is normally automatically overridden in subclasses

    It can occurs only when the repository or entity is not in the Jandex index. Jandex is used to index all the code of your application to avoid using reflection and classpath scanning to discover classes. If your entity / repository is not in the index this means it's not part of your application as we automatically index the classes of your application, so it must be inside an external JAR.

    Usually, this is solved by adding the Jandex plugin to index the code of the external JAR (in fact there is multiple way to do this, see How to Generate a Jandex Index).

    An extension suffer from the same issue as extensions are not indexed by default. But from an extension you can index the needed classes via a build step wich is more easy and avoid polluting the index with classes that are not needed.

    This can be done by generating a new AdditionalIndexedClassesBuildItem(UserRepository.class.getName()) inside a build step.