Skip to content

Provide an alternative way of initializing the SimpleGraphQLServlet #60

Closed
@kaqqao

Description

@kaqqao

I often get asked what to do with the servlet instance once it's created, as the servlet spec provides no programmatic way to register it. Some servlet containers do, when started programmatically (e.g. Jetty), but there's nothing portable. Spring also allows this, but if you already have Spring, creating a custom servlet is already a strange requirement, in the face of Spring MVC controllers etc.

So what people end up doing is what I did in the HowToGraphQL tutorial: subclass SimpleGraphQLServlet, handle the entire setup in the constructor, and register that subclass with the container (using @WebServlet or web.xml) so the container can initialize it as usual. The problem with this is that all the setup steps need to be static and weirdly inlined as the call to super needs to be the very first thing in the constructor. This is very unintuitive and cumbersome. Worse yet, until recently, there was no accessible non-deprecated constructor to call from the subclass, making the only obvious strategy obsolete.

So what I propose is to allow SimpleGraphQLServlet to initialize its state in the usual Servlet#init(ServletConfig) method instead of the constructor. This method exists in the spec exactly because the constructor is often a very inconvenient place to setup servlets.

E.g.

class SimpleGraphQLServlet {
    
    @Override
    public void init(ServletConfig config) {
        Builder builder = getConfiguration();
        if (builder != null) {
            this.schemaProvider = builder.schemaProvider;
            ... // the same as the current constructor
        }
    }
   
    //this is for the subclasses to optionally override
    protected Builder getConfiguration() {
        return null;
    }
}

This would allow a very vanilla use of the servlet, compatible with any container with no surprises or workarounds needed:

@WebServlet(urlPatterns = "/graphql") //or via web.xml
public class GraphQLEndpoint extends SimpleGraphQLServlet {

    @Override
    protected Builder getConfiguration() {
       return SimpleGraphQLServlet.builder(schema)
           .withInstrumentation(..) //etc
    }
}

This is just a quick example of what I mean. Instead of a Builder, getConfiguration could return some Configuration object you could get e.g. by calling Builder#toConfiguration instead of Builder#build or whatever.

I could, of course, implement this if you'd want me to.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions