Best Practices for Custom Resource Implementation

In the other topic, I’m facing a very weird problem due to which XWiki fails to start properly with internal server error. I drilled down the problem to my custom endpoints, which is more or less implemented as following. Two of the endpoints /liveness and /readiness are invoked by kubernetes every 10 seconds, even when the server starts (and have not yet initialized it properly) which probably causes the problem in my other topic.

My questions are:

  • Do we have any thread or synchronization problem? Do we need to protect any data here? container or provider?

  • My handlers are basically derived from AbstractResourceReference because that makes it easy to handle the requests, as shown below. Could that be a problem for internal server error? I don’t see any reason though.

  • How do I ensure that my custom resource does not get used until the wiki is initialized properly?

@Component
@Named("snawaz")
@Singleton
public class CustomResourceReferenceHandler extends AbstractResourceReferenceHandler<ResourceType> {
    public static final ResourceType SNAWAZ_TYPE = new ResourceType("snawaz");
   
    @Inject
    private Container container;

    @Inject
    private Provider<XWikiContext> provider;

    @Override
    public List<ResourceType> getSupportedResourceReferences() {
        return Collections.singletonList(SNAWAZ_TYPE);
    }

    @Override
    public void handle(ResourceReference resourceReference, ResourceReferenceHandlerChain chain) throws ResourceReferenceHandlerException {
        final Request request = container.getRequest();
        final Response response = container.getResponse();
        final handler = (AbstractRequestHandler) resourceReference;

        handler.handle(request, response, provider.get());

        if (chain != null) {
            chain.handleNext(resourceReference);
        }
    }
}

public abstract class AbstractRequestHandler extends AbstractResourceReference {
      
    // code removed for brevity

    public abstract void handle(Request request, Response response, XWikiContext context);

}

@Component
@Named("snawaz")
@Singleton
public class CustomResourceReferenceResolver extends AbstractResourceReferenceResolver {
    
    @Override
    public ResourceReference resolve(ExtendedURL extendedURL, ResourceType resourceType, Map<String, Object> parameters) throws CreateResourceReferenceException, UnsupportedResourceReferenceException {
          return handlerFor(getUrl(extendedURL));
       }

    private AbstractRequestHandler handlerFor(String url) throws UnsupportedResourceReferenceException {
        if (url.startsWith("/slack-events")) {
            return new SlackRequestHandler();
        } else if (url.startsWith("/readiness") || url.startsWith("/liveness")) {
            return new ProbesRequestHandler();
        } else if (url.startsWith("/sync")) {
            return new SyncRequestHandler();
        } else {
            throw new UnsupportedResourceReferenceException("blah");
        }
    }
}

These are the classes/interfaces that I’ve implemented. There are few more inferfaces though in the Resource API docs, which I’ve not implemented, as the above seems to have worked for me when I don’t try to hit it before the wiki gets initialized.