Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jersey-dev] [External] : Jersey servlet failing to intercept the api calls

I was able to fix the issue with this help. Thanks a lot. 

Best,
Aniruddha
========


On Thu, May 20, 2021 at 3:15 AM Jan Supol <jan.supol@xxxxxxxxxx> wrote:
Hi,
The message 
"org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization."
tells you the resource class is not understood by Jersey. I assume it is because you use the spring @RequestBody annotation instead of JAX-RS @Context annotation. I am not sure you would be able to inject the Jetty-specific Request, though.
-- Jan

From: jersey-dev <jersey-dev-bounces@xxxxxxxxxxx> on behalf of Aniruddha Tekade via jersey-dev <jersey-dev@xxxxxxxxxxx>
Sent: Wednesday, May 19, 2021 10:23 PM
To: JETTY user mailing list <jetty-users@xxxxxxxxxxx>
Cc: Aniruddha Tekade <atekade@xxxxxxxxxxxx>; jersey-dev@xxxxxxxxxxx <jersey-dev@xxxxxxxxxxx>
Subject: [External] : [jersey-dev] Jersey servlet failing to intercept the api calls
 
Hello Community,

I have been stuck at this issue for a long time now and need help in identifying what am I doing wrong. 
I have Jetty 11 and Jersey 3.0.2 and Swagger-core 2.1.9. I am wondering if any of the following are wrong in my project:
  1. Jetty & Jersey integration
  2. Dependencies w.r.to Jetty and Jersey
  3. Annotations of API
My control flow is as follows:
  1. Created jetty server that has 128 queue size
  2. Created a jetty servlet holder
  3. Added Jersey servlet so intercept / scan all my API paths
  4. I use Jakarta namespace for this project (you can find in the bottommost gradle for the dependencies )
But when I run the server with the above setting, I get:
Caused by: org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.

However, all my API calls are accessible without jersey or swagger servlet added and I confirmed this by exercising them using python script and also using postman. Now that I want to generate a swagger.json or openapi.yaml for all my apis, I try to scan using jersey model as follows:

// Setup API resources
ServletHolder jersey = servletContextHandler.addServlet(ServletContainer.class, "/api/*");
jersey.setInitOrder(1);
jersey.setInitParameter("jersey.config.server.provider.packages", "com.cloudian.hfs.handlers;io.swagger.v3.jaxrs2.integration.resources");

Where com.cloudian.hfs.handlers contain all resource classes and apis. What am I doing wrong? For detailed code: 

Jersy and Jetty integration:

import com.cloudian.hfs.handlers.*;
import io.swagger.v3.jaxrs2.integration.OpenApiServlet;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class StartHFS {

    public static void main(String[] args) throws Exception {
        System.out.println("StartHFS");

        // Create and configure a ThreadPool.
        QueuedThreadPool threadPool = new QueuedThreadPool();
        threadPool.setName("server");

        // Create a Server instance.
        Server server = new Server(threadPool);

        // HTTP configuration and connection factory.
        HttpConfiguration httpConfig = new HttpConfiguration();
        HttpConnectionFactory http11 = new HttpConnectionFactory(httpConfig);

        // Create a ServerConnector to accept connections from clients.
        ServerConnector connector = new ServerConnector(server, 1, 1, http11);
        connector.setPort(8080);
        connector.setHost("0.0.0.0");
        connector.setAcceptQueueSize(128);
        server.addConnector(connector);

        addHandlers(server);

        // Start the Server so it starts accepting connections from clients.
        try {
            server.start();
            server.join();
        } catch (Exception ex) {
            Logger.getLogger(StartHFS.class.getName()).log(Level.SEVERE, "Fail to start HFS Server", ex);
        } finally {
            server.destroy();
        }

        System.out.println("StartHFS DONE");
    }

static void addHandlers(final Server server) throws Exception {
        ContextHandlerCollection contexts = new ContextHandlerCollection();
        server.setHandler(contexts);

        ContextHandler featureStoreHandler = new ContextHandler("/featurestore");
        featureStoreHandler.setHandler(new FeatureStoreHandler());
        contexts.addHandler(featureStoreHandler);

        // Setup Jetty Servlet
        ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        servletContextHandler.setContextPath("/");
        contexts.addHandler(servletContextHandler);

        // Setup API resources
        ServletHolder jersey = servletContextHandler.addServlet(ServletContainer.class, "/api/*");
        jersey.setInitOrder(1);
        jersey.setInitParameter("jersey.config.server.provider.packages", "com.cloudian.hfs.handlers;io.swagger.v3.jaxrs2.integration.resources");


        // Expose API definition independently into yaml/json
        ServletHolder openApi = servletContextHandler.addServlet(OpenApiServlet.class, "/openapi/*");
        openApi.setInitOrder(2);
        openApi.setInitParameter("openApi.configuration.resourcePackages", "com.cloudian.handlers;io.swagger.sample.resource");
    }
}


Gradle Dependencies:

plugins {
    id 'java'
    id "io.swagger.core.v3.swagger-gradle-plugin" version "2.1.9"
}

group 'com.cloudian'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    // Basic Gradle dependencies
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'

    // Logging dependencies
    runtimeOnly 'org.slf4j:slf4j-api:1.7.7'
    runtimeOnly 'org.slf4j:slf4j-log4j12:1.7.7'

    // Jetty dependencies
    implementation 'org.eclipse.jetty:jetty-server:11.0.0'
    implementation 'org.eclipse.jetty:jetty-servlet:11.0.0'
    implementation 'org.eclipse.jetty:jetty-util:11.0.0'

    // Jersey dependencies
    implementation 'org.glassfish.jersey.containers:jersey-container-jetty-http:3.0.2'
    implementation 'org.glassfish.jersey.containers:jersey-container-servlet-core:3.0.2'
    //    implementation 'org.glassfish.jersey.core:jersey-server:3.0.2'
    implementation 'org.glassfish.jersey.media:jersey-media-json-binding:3.0.2'
    implementation 'org.glassfish.jersey.core:jersey-common:3.0.2'
    // Jetty and Jersey InjectionManagerFactory dependency [Required]
    implementation 'org.glassfish.jersey.inject:jersey-hk2:3.0.2'
    // Enable JAXBContext and WADL Jersey [Required]
    implementation 'org.glassfish.jaxb:jaxb-runtime:3.0.1'

    // Redis & Json dependencies
    implementation 'org.springframework.data:spring-data-redis:2.4.3'
    implementation 'redis.clients:jedis:3.3.0'
    implementation group: 'org.json', name: 'json', version: '20201115'

    // Swagger, Jakarta deps
    implementation 'org.apache.commons:commons-lang3:3.7'
    implementation 'io.swagger.core.v3:swagger-jaxrs2-jakarta:2.1.9'
    implementation 'jakarta.ws.rs:jakarta.ws.rs-api:3.0.0'
    implementation 'jakarta.servlet:jakarta.servlet-api:5.0.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

resolve {
    outputFileName = 'MyRestAPI'
    outputFormat = 'YAML'
    prettyPrint = 'TRUE'
    classpath = sourceSets.main.runtimeClasspath
    buildClasspath = classpath
    resourcePackages = ['io.test']
    outputDir = file('test')
}

test {
    useJUnitPlatform()
}

jar {
    manifest {
        attributes "Main-Class": "com.cloudian.hfs.StartHFS"
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Annotation of my APIs:
@Path("/featurestore/")
@Produces({"application/json", "application/xml"})
public class FeatureStoreHandler extends AbstractHandler {

    // Some final CONSTANTS for api implementation

    @Override
    public void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {}

    @POST
    @Path("/create")
    @Consumes("application/json")
    public void createFeatureGroup(@RequestBody Request jettyRequest, @RequestBody HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException, JedisException {}

    @DELETE
    @Path("/delete")
    @Consumes("application/json")
    public void deleteFeatureGroup(@RequestBody Request jettyRequest, @RequestBody HttpServletRequest request, HttpServletResponse response) throws IOException, JedisException, JSONException {}

    @GET
    @Path("/describe")
    public void describeFeatureGroup(@RequestBody Request jettyRequest, @RequestBody HttpServletRequest request, HttpServletResponse response) throws IOException, JedisException, JSONException {}
}

Best,
Aniruddha
========

Back to the top