0
    @GET
    @Path("/book")
    public Response getBook(@BeanParam Filter filter) {

    }

Filter paramater is getting initialized but nothing is set in the bean

class Filter {@QueryParam("author")String author}

I do have setter and getter for all properties present in Filter object.

F.Y.I. I am using the HK2 guice-bridge.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
pinakin
  • 422
  • 4
  • 16
  • What is `author` supposed to represent? A `@FormParam`, `@QueryParam`, `@HeaderParam`, etc? Have you added the annotation accordingly? – Paul Samsotha Apr 30 '17 at 03:36
  • Yes I did added annotation, It is QueryParam updated the question. – pinakin Apr 30 '17 at 04:19
  • So are you saying that this works _without_ guice, and that guice is the problem? Can you confirm this. Just trying to figure out why you're mentioning guice at all. – Paul Samsotha Apr 30 '17 at 04:21
  • check this out https://github.com/medvedev/beanparam-jersey-guice some one has sample project to show issue with Jersey @BeanParam and Guice DI framework.. – pinakin Apr 30 '17 at 04:23
  • I don't use the library ([dropwizard-guice](https://github.com/HubSpot/dropwizard-guice)) you are using, but looks to be an [open issue](https://github.com/HubSpot/dropwizard-guice/issues/93) – Paul Samsotha Apr 30 '17 at 04:26
  • I am not using dropwizard-guice. I am just using https://hk2.java.net/guice-bridge/. Is there any other way to have Guice and Jersey working together ? Seems There are lot of issue with Guice and Jersey 2.X – pinakin Apr 30 '17 at 04:28
  • It could be done without bridge, you can instantiate class with Guice and register it in the Jersey context. Or you can use Guice Webserver module which work exactly that: https://github.com/sorskod/webserver – sasa Aug 25 '17 at 22:22

2 Answers2

1

I was able to reproduce the problem with guice-bridge. It seems that when the bridge is initialized (via guiceBridge.bridgeGuiceInjector(...)), only the BeanParam's default constructor is being called instead of also setting the properties (or calling the constructor with parameters).

If it's possible in your project, you could try to provide a constructor with parameters.

This is a simple app:

public class App extends ResourceConfig {

   @Inject
   public App(final ServiceLocator serviceLocator) {
     register(Service.class);

     final Injector injector = initializeInjector(serviceLocator);
   }

   private Injector initializeInjector(final ServiceLocator serviceLocator) {
     GuiceBridge.getGuiceBridge()
         .initializeGuiceBridge(serviceLocator);

     final Injector injector = Guice.createInjector(
         new ApplicationModule(serviceLocator));
     final GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
     guiceBridge.bridgeGuiceInjector(injector);
     return injector;
   }

}

The used service:

@Path("service")
public class Service {

  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  public Response save(@Valid @BeanParam final SimpleBean bean) {
    System.out.println(bean.getProperty());
    return Response.status(Status.CREATED)
        .build();
  }
}

And here's a simple bean:

public class SimpleBean {

  // Avoid this constructor!
  // public SimpleBean() {
  //  System.out.println("constructor called");
  // }

  public SimpleBean(@FormParam("property") final String property) {
    this.property = property;
    System.out.println("constructor with params called: " + property);
  }

  @Length(max = 100)
  @NotBlank
  private String property;

  public String getProperty() {
    System.out.println("getter called");
    return property;
  }

  public void setProperty(final String property) {
    System.out.println("setter called with " + property);
    this.property = property;
  }

}

Using Guice version 4.1.0, guice-bridge version 2.4.0, Jersey version 2.25.1 and Javax servlet version 3.1.0.

Lukas S.
  • 11
  • 2
0

You can try to use Guice-Jersey without bridge. There is a project called "Guice Webserver Module" which integrates Guice with Jersey 2, Jetty and Jackson where this approach is implemented.

What you need to do is to bind your resource in Guice context, e.g.

public class MyModule extends AbstractModule() {
    public void configure() {
            bind(BooksResource.class);
    }

There is a Jersey's feature which will scan for all binding annotated with @Path, and will register instance in Jersey's context after instantiation:

public boolean configure(FeatureContext context) {
    injector.getBindings().entrySet()
        .stream()
        .filter(entry -> entry.getKey().getTypeLiteral().getRawType().getAnnotation(Path.class) != null)
        .map(entry -> injector.getInstance(entry.getKey()))
        .forEach(context::register);

    return true;
  }

There is also a example (written as part of integration test) for BeanParams - BeanParamsIntegrationTest

sasa
  • 2,443
  • 5
  • 23
  • 35