2016-05-18 16 views
1

Mit den folgenden Abhängigkeiten (Gradle) zur Verfügung:Making Business Domain-Objekte auf Jersey Servletkontext in eingebetteten Jetty-Server

  • org.glassfish.jersey.containers:jersey-container-servlet:2.22.2

  • org.eclipse.jetty:jetty-servlet:9.3.2.v20150730

Ich habe eine eingebettete Jetty Server, mit einem Jersey Servlet Container ... so etwas wie ...

package mypkg.rest.jersey; 

import org.eclipse.jetty.server.Server; 
import org.eclipse.jetty.servlet.ServletContextHandler; 
import org.eclipse.jetty.servlet.ServletHolder; 
import org.glassfish.jersey.server.ServerProperties; 
import org.glassfish.jersey.servlet.ServletContainer; 
import se.transmode.tnm.alarm.api.AlarmRetrieval; 
import mypkg.rest.RestServer; 
import mypkg.rest.jersey.serviceImpl.ModelAdapter; 

public class JerseyBasedRestServer implements RestServer { 

public static final int INITIALIZE_ON_USE = 0; 
private Server server; 
private final ServletContextHandler context; 
private final ServletHolder servlet; 
private final ModelAdapter modelAdapter; 

public JerseyBasedRestServer(BusinessObjects businessObjects) { 
    this.modelAdapter = new ModelAdapter(businessObjects); //I want this instance to somehow be available for my ServletContainer to use. 

    context = new ServletContextHandler(ServletContextHandler.SESSIONS); 
    servlet = context.addServlet(ServletContainer.class, "/*"); 
    servlet.setInitOrder(INITIALIZE_ON_USE); 
    servlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "mypackage.jersey.generated.api.service"); 
    servlet.setInitParameter(ServerProperties.MEDIA_TYPE_MAPPINGS, "json : application/json"); 
    context.setContextPath("/"); 
} 

private void startServlet() { 
    try { 
     servlet.start(); 
     servlet.initialize(); 
    } catch (Exception e) { 
     log.error("Failed to initialize servlet. {}", e.getMessage()); 
    } 
} 

@Override 
public void init(int port) { 
    server = new Server(port); 
    server.setHandler(context); 
    try { 
     server.start(); 
     server.join(); 
     startServlet(); 
    } catch (Exception e) { 
     log.error("Failed to start jetty server for rest interface"); 
    } finally { 
     server.destroy(); 
    } 
} 

Der Jersey Container wird Servercode und Modell generiert unter Verwendung des Swagger Code-gen Werkzeug

https://github.com/swagger-api/swagger-codegen#getting-started

welches liefert das erzeugte Modell, JacksonJsonProvider und eine RestApi Klasse ausgeführt:

package mypackage.jersey.generated.api.service 

Path("/") 
public class RestApi { 
    private final RestApiService delegate = new RestApiServiceImpl(); //Integration point of the generated code 

    @GET 
    @Path("/list/") 
    @Consumes({ "application/json" }) 
    @Produces({ "application/json" }) 
    public Response retrieveAlarmList(@Context SecurityContext securityContext) throws NotFoundException { 
    return delegate.retrieveAlarmList(securityContext); 
    } 
} 

Um den generierten Code zu integrieren, müssen wir selbst RestApiServiceImpl implementieren.

Der ModelAdapter Job besteht darin, unsere Geschäftsobjekte in das generierte Ruhe-Modell zu konvertieren.

Die Frage ist also, wie kann ich die Instanz des Adapters unserer Geschäftsobjekte machen, in diesem Fall ModelAdapter, die außerhalb des Kontextes des Jersey-Servlet-Kontext zur Verfügung, die RestApi Klasse liegt, oder besser gesagt die RestApiServiceImpl?

Ich verstehe aus dem Lesen der letzten 24 Stunden, dass ich eine Art Context Dependency Injection entweder über Jetty, Jersey oder eine andere Bibliothek verwenden muss (Weld scheint viel zu erscheinen), und habe verschiedene Kombinationen ausprobiert @Inject, @Context, etc etc, aber sind zu dem Schluss gekommen, dass ich keine Ahnung habe, was ich eigentlich tue ... Ich bin nicht einmal sicher, ob ich genug über die Situation verstehe, um meine Frage richtig zu formulieren.

Weitere Informationen können auf Anfrage zur Verfügung gestellt werden.

Jede Hilfe wird geschätzt.

EDIT: hinzugefügt hier einen Link zu https://github.com/englishbobster/JersetAndJetty

@peeskillets Vorschläge verwenden, aber immer noch nicht funktioniert.

Antwort

2

Als erstes müssen Sie DI arbeiten, ist ein AbstractBinder. Hier stellen Sie Ihre Objekte für die Injektion bereit.

class Binder extends AbstractBinder { 
    @Override 
    protected void configure() { 
     bind(modelAdapter).to(ModelAdapter.class); 
    } 
} 

Dann müssen Sie den Ordner mit Jersey registrieren. Der einfachste Weg ist, sich in Jersey's ResourceConfig zu registrieren. In Ihrem Fall verwenden Sie keinen. Sie konfigurieren alles in der "web.xml". Sehen Sie sich hierzu this post an.

Wenn Sie möchten, um Ihre Konfiguration ändern, um eine ResourceConfig, zu verwenden, die ich persönlich eher verwenden möchten, können Sie dies tun

package com.some.pkg; 

public class JerseyConfig extends ResourceConfig { 
    public JerseyConfig() { 
     packages("mypackage.jersey.generated.api.service"); 
     property(ServerProperties.MEDIA_TYPE_MAPPINGS, "json : application/json"); 
     register(new Binder()); 
    } 
} 

dann mit Jetty es zu konfigurieren, können Sie

tun
servlet.setInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, 
         "com.some.pkg.JerseyConfig"); 

Jetzt können Sie diese anderen zwei Init-Parameter loswerden, wie Sie es innerhalb der ResourceConfig konfigurieren.

Ein anderer Weg, ohne init-params ist

ResourceConfig config = new JerseyConfig(); 
ServletHolder jerseyServlet = new ServletHolder(ServletContainer(config)); 
context.addServlet(jerseyServlet, "/*"); 

Ganzer Beispiel des letzten Code-Schnipsel zu tun, here.

Jetzt können Sie nur die ModelAdapter injizieren so ziemlich überall in Jersey

In einem Feld

@Inject 
private ModelAdapter adapter; 

Oder in einem contructor

@Inject 
public RestApi(ModelAdapter adapter) { 
    this.adapter = adapter; 
} 

oder Methodenparameter

@GET 
public Response get(@Context ModelAdapter adapter) {} 
+0

OK danke für die Antwort. Ich habe etwas ähnliches während meiner Experimente versucht. Ich habe gerade Ihr oben beschriebenes Rezept ausprobiert, eine Sammelmappe und eine Ressourcenkonfiguration erstellt, dann die Injektion in das Feld verwendet, bekomme aber immer noch eine Nullzeigerausnahme, wenn ich mein ModelAdapter verwende. Was ist der beste Weg, um den Kontext in einem Debugger zu sehen (wenn überhaupt möglich)? – Englishbob

+0

BTW Ich habe nie eine web.xml für die Konfiguration verwendet, (Angst vor XML) und versucht, alles programmgesteuert zu machen. – Englishbob

+1

Es sollte in die "RestApi" einfach gut injizieren. Wenn Sie versuchen, es in den Dienst zu injizieren, können Sie den Dienst nicht selbst instanziieren. Sie müssen 1) Binden Sie den Service mit der Mappe auch, und 2) _Inject_ der Service in die RestApi, nicht instanziieren –