2016-09-13 23 views
8

Tôi created a project để kiểm tra việc tiêm phụ thuộc do Google Guice cung cấp trong tài nguyên Jax-rs của tôi, sử dụng Resteasy.Resteasy and Google Guice: cách sử dụng nhiều @ApplicationPath và tài nguyên với @Injection?

ý định của tôi là:

  • Sử dụng nhiều @ApplicationPath cho các phiên bản của API của tôi. Trong mỗi lớp được chú thích với @ApplicationPath tôi tải một tập hợp các lớp cho phiên bản cụ thể.
  • Mỗi tài nguyên có @Inject (từ Google Guice) trong công cụ xây dựng của mình để tiêm một số dịch vụ.

Tôi đã tạo hai lớp được chú thích với @ApplicationPath: ApplicationV1RSApplicationV2RS. Trong cả hai tôi đã thêm các lớp tài nguyên giống nhau (UserResourceHelloResource), chỉ cho bài kiểm tra của tôi.

My Module được cấu hình như thế này:

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); 
    } 
} 

Khi tôi gọi http://localhost:9095/v1/hello/world hoặc http://localhost:9095/v2/hello/world, tôi nhận được lỗi tương tự:

java.lang.RuntimeException: RESTEASY003190: Could not find constructor 
    for class: org.jboss.resteasy.examples.guice.hello.HelloResource 

Vâng, như tôi mong đợi, điều này không hoạt động. Google Guice không phải là "thông minh" để khởi tạo các lớp tài nguyên bằng cách sử dụng construtor cho tôi.

Nhưng tôi không thể tìm được cách để làm việc. Để thực sự thành thật, tôi thực sự bối rối về cách Google Guice, Jetty và Resteasy chơi với nhau trong trường hợp này.

Nếu tôi từ bỏ ý tưởng về sử dụng @ApplicationPath, tài nguyên của tôi làm việc với Google Guice cấu hình của tôi HelloModule như thế này:

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); 
    } 
} 

Nhưng trong trường hợp này, tôi đi qua sự kiểm soát đăng ký nguồn lực của tôi (HelloResourceUserResource) đến Guice. Nó không linh hoạt đối với tôi, tôi không thể thiết lập nhiều số @ApplicationPath của mình.

Vì vậy, những gì tôi thiếu hoặc không hiểu?

Tôi đã tạo một dự án có mã có vấn đề. Rất dễ thiết lập và thử nghiệm: https://github.com/dherik/resteasy-guice-hello/tree/so-question/README.md

Cảm ơn!

Trả lời

1

Khi bạn có phương thức getClasses trong ứng dụng của bạn thì nó cố gắng tạo cá thể cho tất cả các tài nguyên đã đăng ký bằng cách sử dụng hàm tạo mặc định bị thiếu trong lớp Tài nguyên của chúng tôi. Một cách là tạo một hàm tạo mặc định và Tiêm các phụ thuộc thông qua hàm setter Injection. Và sau đó thay vì ghi đè getClasses trong ApplicationV1RSApplicationV2RS bạn ghi đè getSingletons. Vì Tài nguyên có thể là Singleton.

Dưới đây là những thay đổi mà tôi đã thực hiện để làm cho nó hoạt động theo cách bạn muốn.

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); 
    } 
} 

Thêm @Singleton đến lớp dịch vụ của bạn.

Hy vọng điều đó sẽ hữu ích.

Tôi cũng đã đẩy mã đến forked repo. kiểm tra xem nó ra

+0

Và web.xml vẫn không cần thiết? Tôi có đúng không? – SayusiAndo

Các vấn đề liên quan