Как включить ввод CDI в веб-сервисе (jaxrs/jersey) на java se running grizzly?
Как разрешить вложение ресурсов CDI в резервные ресурсы веб-сервисов? Я запускаю стандартную java, используя сварку 2 (cdi), джерси (jaxrs) и гризли (веб-сервер). Вот мой простой веб-ресурс:
import training.student.StudentRepository;
import javax.inject.Inject;
import javax.ws.rs.*;
@Path("student")
public class StudentWebResource {
@Inject
private StudentRepository studentRepository;
@GET
@Path("count")
@Produces(MediaType.TEXT_PLAIN)
public Integer getCount() {
return studentRepository.studentCount();
}
}
И вот как я получил сварку, начиная свой простой веб-сервер:
public class Main {
public static void main(String[] args) throws Exception {
startCdiApplication();
}
public static void startCdiApplication() throws Exception {
Weld weld = new Weld();
try {
WeldContainer container = weld.initialize();
Application application = container.instance().select(WebServer.class).get();
application.run();
}
finally {
weld.shutdown();
}
}
}
И код, который, как я подозреваю, нужно будет изменить, чтобы сообщить трикотаж, чтобы использовать сварку для разрешения инъекций CDI:
...
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
public class WebServer implements Application {
/*
* startup the grizzly http server to make available the restful web services
*/
private void startWebServer() throws IOException, InterruptedException {
final ResourceConfig resourceConfig = new ResourceConfig().packages("training.webservice").register(new JacksonFeature());
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(getBaseUri(), resourceConfig);
server.start();
Thread.currentThread().join();
}
...
@Override
public void run() throws IOException, InterruptedException {
startWebServer();
}
}
Ответы
Ответ 1
После просмотра fooobar.com/questions/67024/... я выполнил следующее решение. Не уверен, что это лучший маршрут, но он сработал.
Я создал привязку hk2 и зарегистрировал связующее:
public class WebServiceBinder extends AbstractBinder {
@Override
protected void configure() {
BeanManager bm = getBeanManager();
bind(getBean(bm, StudentRepository.class))
.to(StudentRepository.class);
}
private BeanManager getBeanManager() {
// is there a better way to get the bean manager?
return new Weld().getBeanManager();
}
private <T> T getBean(BeanManager bm, Class<T> clazz) {
Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
CreationalContext<T> ctx = bm.createCreationalContext(bean);
return (T) bm.getReference(bean, clazz, ctx);
}
}
Затем изменил экземпляр ResourceConfig сверху до:
final ResourceConfig resourceConfig = new ResourceConfig()
.packages("training.webservice")
.register(new JacksonFeature())
.register(new WebServiceBinder());
Ответ 2
Выбранный ответ датируется некоторое время назад. Нецелесообразно объявлять каждую привязку в обычном связующем HK2.
Мне просто пришлось добавить одну зависимость. Несмотря на то, что он был разработан для Glassfish, он идеально вписывается в другие контейнеры. Я использую Tomcat/Grizzly.
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.14</version>
</dependency>
Вот пример с JerseyTest (тот же принцип, если вы запустите его из основного метода). Мне просто нужно было объявить зависимость от сварки и объявить контейнер Weld перед созданием моих ресурсов - как вы это делали, - и это работает из коробки.
public class GrizzlyTest extends JerseyTest {
private Weld weld;
private WeldContainer container;
@Override
protected Application configure() {
weld = new Weld();
container = weld.initialize();
return new ResourceConfig(MyResource.class);
}
@Test
public void test() {
System.out.println(target("myresource").request().get(String.class));
}
@After
public void after() {
weld.shutdown();
}
}
Ответ 3
Так как по крайней мере Weld 2.2.0.Final, нет необходимости испортить HK2 Binder.
В качестве официальной Weld документации говорится, что вам просто нужно зарегистрировать org.jboss.weld.environment.servlet.Listener
. Код отключен из документа:
public class Main {
public static void main(String[] args) throws ServletException, LifecycleException {
Tomcat tomcat = new Tomcat();
Context ctx = tomcat.addContext("/", new File("src/main/resources").getAbsolutePath());
Tomcat.addServlet(ctx, "hello", HelloWorldServlet.class.getName());
ctx.addServletMapping("/*", "hello");
ctx.addApplicationListener(Listener.class.getName());
tomcat.start();
tomcat.getServer().await();
}
public static class HelloWorldServlet extends HttpServlet {
@Inject
private BeanManager manager;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain");
resp.getWriter().append("Hello from " + manager);
}
}
}
Над сервлет-слушателем управляет весь жизненный цикл контейнера Weld. Поэтому нет необходимости:
Weld weld = new Weld();
WeldContainer container = weld.initialize();
UPDATE
Как отметил @EdMelo, HTTP-сервер Grizzly не является полностью совместимым контейнером Servlet. Я не знал этого, спасибо за этот намек. Поэтому я не уверен, если мой ответ по-прежнему применяется здесь.