dependency-injectionjerseyjersey-2.0uribuilder

Jersey injection


Is there a way to change the implementation of UriInfo that's injected into all the resources and classes? I want to keep most of the implementation the same, but just change one part of it (the part that provides a UriBuilder - I want to provide a different implementation of the UriBuilder).


Solution

  • You can create wrapper around the original UriInfo

    public class MyUriInfo implements UriInfo {
    
        private final UriInfo delegate;
    
        public MyUriInfo(UriInfo uriInfo) {
            this.delegate = uriInfo;
        }
    
        @Override 
        public String getPath() { 
            return delegate.getPath(); 
        }
    
        @Override
        public UriBuilder getRequestUriBuilder() {
            return new MyUriBuilder();
        }
        ...
    }
    

    Then just create a Factory to return your custom UriInfo. This Factory will be used by the DI framework to inject the UriInfo.

    public class MyUriInfoFactory 
            extends AbstractContainerRequestValueFactory<MyUriInfo> {
    
        @Override
        public MyUriInfo provide() {
            return new MyUriInfo(getContainerRequest().getUriInfo());
        }
    }
    

    Then just create the AbstractBinder and register it with the ResourceConfig

    public class Binder extends AbstractBinder {
    
        @Override
        protected void configure() {
            bindFactory(MyUriInfoFactory.class)
                    .to(UriInfo.class)
                    .in(RequestScoped.class)
                    .proxy(true)
                    .proxyForSameScope(false)
                    .ranked(10);
        }
    }
    
    public class AppConfig extends ResourceConfig {
        public AppConfig() {
            register(new Binder());
        }
    }
    

    If you are using web.xml, check out this post.

    Now you should be able to just inject it

    @GET
    public String get(@Context UriInfo uriInfo) {
        return uriInfo.getClass().getName();
    }
    

    If you want to be able to retain being able to inject the original UriInfo, you can change the binding to

    bindFactory(MyUriInfoFactory.class)
            .to(MyUriInfo.class)  // <--- Change here to MyUriInfo
            .in(RequestScoped.class)
            .proxy(true)
            .proxyForSameScope(false)
            .ranked(10);
    

    This way, you would need to inject MyUriInfo

    @GET
    public String get(@Context MyUriInfo uriInfo) {
        return uriInfo.getClass().getName();
    }
    

    Doing this, you are still able to inject the original UriInfo if you needed to.

    See Also: