Resteasy и Google Guice: как использовать несколько @ApplicationPath и ресурс с @Injection?
Я создал проект для проверки внедрения зависимостей, предлагаемого Google Guice на моих ресурсах Jax-rs, с помощью Resteasy.
Мои намерения таковы:
- Используйте несколько
@ApplicationPath
для версий моего API. В каждом классе отмечены@ApplicationPath
Я загружаю набор классов для конкретной версии. - Каждый ресурс имеет
@Inject
(из Google Guice) в своем конструкторе для внедрения некоторых сервисов.
Я создал два класса с пометкой @ApplicationPath
: ApplicationV1RS
а также ApplicationV2RS
, В оба я добавил одинаковые ресурсы классов (UserResource
а также HelloResource
), только для моего теста.
Мой модуль настроен так:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
Когда я звоню http://localhost:9095/v1/hello/world
или же http://localhost:9095/v2/hello/world
Я получаю ту же ошибку:
java.lang.RuntimeException: RESTEASY003190: Could not find constructor
for class: org.jboss.resteasy.examples.guice.hello.HelloResource
Ну, как я и ожидал, это не работает. Google Guice не является "умным" для создания экземпляров классов ресурсов, используя для меня конструктор.
Но я не могу найти способ работать. Честно говоря, я не совсем понимаю, как Google Guice, Jetty и Resteasy играют друг с другом в этом сценарии.
Если я откажусь от идеи использования @ApplicationPath
мои ресурсы работают с Google Guice HelloModule
как это:
public class HelloModule implements Module
{
public void configure(final Binder binder)
{
binder.bind(HelloResource.class);
binder.bind(IGreeterService.class).to(GreeterService.class);
binder.bind(UserResource.class);
binder.bind(IUserService.class).to(UserService.class);
}
}
Но в этом случае я передаю управление для регистрации своих ресурсов (HelloResource
а также UserResource
) Guice. Это не гибко для меня, я не могу настроить несколько @ApplicationPath
,
Итак, что я упускаю или не понимаю?
Я создал проект с проблемным кодом. Очень прост в настройке и тестировании: https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md
Спасибо!
1 ответ
Когда у тебя есть getClasses
Затем в вашем Приложении он пытается создать экземпляр для всех зарегистрированных ресурсов, используя конструктор по умолчанию, отсутствующий в нашем классе Resources. Один из способов - создать конструктор по умолчанию и внедрить зависимости через метод установки Injection. И тогда вместо переопределения getClasses
в ApplicationV1RS
а также ApplicationV2RS
ты переопределяешь getSingletons
, Так как ресурсы могут быть синглтон.
Ниже приведены изменения, которые я сделал, чтобы все заработало так, как вы хотите.
ApplicationV1RS.java
@ApplicationPath("v1")
public class ApplicationV1RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV1RS(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
ApplicationV2RS.java
@ApplicationPath("v2")
public class ApplicationV2RS extends Application {
private Set<Object> singletons = new HashSet<Object>();
public ApplicationV2RS(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons() {
Injector injector = Guice.createInjector(new HelloModule());
HelloResource helloResource = injector.getInstance(HelloResource.class);
UserResource userResource = injector.getInstance(UserResource.class);
singletons.add(helloResource);
singletons.add(userResource);
return singletons;
}
}
HelloResource.java
@Path("hello")
public class HelloResource {
@Inject
private IGreeterService greeter;
public HelloResource() {
}
@GET
@Path("{name}")
public String hello(@PathParam("name") final String name) {
return greeter.greet(name);
}
}
UserResource.java
@Path("user")
public class UserResource {
@Inject
private IUserService userService;
public UserResource() {
}
@GET
@Path("{name}")
public String hello(@PathParam("name") final String name) {
return userService.getUser(name);
}
}
добавлять @Singleton
к вашим классам обслуживания.
Надеюсь, поможет.
Я также выдвинул код для разветвленного репо. проверить это