Getting hk2 and Jersey to inject classes - java

How can I get Jersey to inject classes without creating and registering factories on a one-for-one basis?
I have the following config:
public class MyConfig extends ResourceConfig {
public MyConfig() {
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(FooFactory.class).to(Foo.class);
bindFactory(BazFactory.class).to(Baz.class);
}
});
}
}
hk2 will now successfully inject Foo and Baz:
// this works; Foo is created by the registered FooFactory and injected
#GET
#Path("test")
#Produces("application/json")
public Response getTest(#Context Foo foo) {
// code
}
But that's not my goal. My goal is to inject objects that wrap these classes. There are many and they each consume different combinations of Foo and Baz. Some examples:
public class FooExtender implements WrapperInterface {
public FooExtender(Foo foo) {
// code
}
}
public class FooBazExtender implements WrapperInterface {
public FooBazExtender(Foo foo, Baz baz) {
// code
}
}
public class TestExtender implements WrapperInterface {
public TestExtender(Foo foo) {
// code
}
// code
}
And so on.
The following does not work:
// this does not work
#GET
#Path("test")
#Produces("application/json")
public Response getTest(#Context TestExtender test) {
// code
}
I could create a factory for each and register it in my application config class, using the bindFactory syntax like I did with Foo and Baz. But that is not a good approach due to the number of objects in question.
I have read much of the hk2 documentation, and tried a variety of approaches. I just don't know enough of how hk2 actually works to come up with the answer, and it seems like a common enough problem that there should be a straightforward solution.

Factories are really only needed for more complex initializations. If you don't need this, all you need to do is bind the service
#Override
protected void configure() {
// bind service and advertise it as itself in a per lookup scope
bindAsContract(TestExtender.class);
// or bind service as a singleton
bindAsContract(TestExtender.class).in(Singleton.class);
// or bind the service and advertise as an interface
bind(TestExtender.class).to(ITestExtender.class);
// or bind the service and advertise as interface in a scope
bind(TestExtender.class).to(ITestExtender.class).in(RequestScoped.class);
}
You also need to add #Inject on the constructors so HK2 knows to inject the Foo and Baz
#Inject
public TestExtender(Foo foo, Baz baz) {}

I wound up using FastClasspathScanner to grab classes from the package(s) I was interested in. Then I called the appropriate bind methods (bindAsContract or bind) in batches, as mentioned in Paul Samsotha's answer (after also adding the appropriate #Inject annotations).
That seemed to be the most expedient method available to emulate autoscanning and avoid having to manually register each class.
It feels like a hack and I'd be surprised if hk2 doesn't have a better method baked in.

Related

how to rewrite this code to avoid switches/casting

Simplified example to give you an idea, hope it's be clear.
I've already added inheritance for Service class to avoid switches I'm having now
class Config {}
class ConfigA extends Config {}
class ConfigB extends Config {}
// service class - different implementation for configA and ConfigB
// normally it would look like
class ServiceA {
public String run(ConfigA configA) {}
}
thus next then I need sth like
class ServiceRunner {
public String run(Config config) {
// if or switch doesn't matter now
if (config instanceof ConfigA) {
return serviceA.run((ConfigA)config);
}
}
}
// main
Config config = configFactory.create(...) // returns ConfigA or ConfigB
String result = serviceRunner.run(config);
Is there a better way to code it I mean without casting?
The only solution I can see is:
interface Service { String run(); }
#RequestScope
class ServiceA implements Service {
private ConfigA config;
public ServiceA(ConfigA configA) {this.configA = configA}
public String run() {
...
}
}
but I'm not convinced it's a good idea to implement service beans as state beans and I'm using CDI (quarkus actually) for DI which it seems doesn't support assisted injection via constructor
Why don't you hide the detail about which Config a given Service handles inside the Service itself? By doing so you could have something like the following:
interface Service {
boolean handlesConfig(Config config)
String run(Config config);
}
class ServiceRunner {
private List<Service> services;
public String run(Config config) {
for (service : services) {
if (service.handles(config)) {
return service.run(config);
}
}
}
}
Seems like it's a case for Bridge pattern. You have parallel hierarchies of service and config. So if tomorrow there is a ServiceC, there would supposedly be a ConfigC. There might be an abstraction which is common in both service and config. Try to find it and abstract it out. Then service would be using that abstraction. And ConfigA, ConfigB would be impls of that abstraction.
Or perhaps, as the replier above mentioned, service should be programmed to the abstract config instead of impls.
Does the Configs have different types of interfaces that can't be extracted into a common interface? In that case, it is violating the Liskov's substitution principle, which requires that all subclasses should be interchangeable. e.g. the hierarchy of Shape <- Rectangle <- Square is wrong, because square is not a type of rectangle (programmatically, of course) - because Rectangle has 2 dimensions, namely length and breadth, while square has one dimension of length only. Making this hierarchy would break the abstraction. Similarly, it might be your case that the hierarchy of Config may not be a hierarchy at all.

How to configure providers with custom parameters?

My class depends on some services which needs to take few parameters and then make network call, currently I am passing those parameters and then creating those services via a factory injected into my class. I need to inject those services as a dependency instead, I know that I can create providers for them but in most of the examples I see that the providers are often bound to the fixed values like serveraddres etc. but I need to give then values during run time.
Below is my example code:
public SomeClass {
private final SomeFactory someFactory;
#Inject
SomeClass(SomeFactory factory) {
someFactory = factory;
}
public Foo getFoo(String fooId) {
FooService fooService = someFactory.getFooService(fooId);
return fooService.getFoo();
}
}
What I need to do is:
public SomeClass {
private final FooService fooService;
#Inject
SomeClass(FooService fooService) {
this.fooService = fooService;
}
public Foo getFoo(String fooId) {
return fooService.getFoo();
}
}
Update 1
Making the use case more clear:
#Provides
#RequestScoped
public SomeService provideSomeService(Dep1 dep1, String code) throws IOException {
return new SomeService.Builder()
.withApplicationName("Foo")
.setCode(code)
.build();
}
Here, code can be null by default and when needed I can give some value in it.
Can I somehow pass arguments to the provider before its created?
If you have a binding for your value (here, code is a String without a binding annotation), then your Update 1 is exactly what the code would look like.
In practice, there are a few differences:
Constants like int and String values are generally annotated with a binding annotation, either #Named or a custom annotation.
If you need to inject a value into an object graph after Guice initialization, but have a deep enough object graph that dependency injection is still a good idea, you can create a child injector. This way you can make a #Named("code") String accessible within one action or object, but not across your entire Guice application.
If your value for code is dynamic enough that it can't be provided through Guice as a key of its own, then you'll have to pass it in using a factory of some sort. For a Builder-based object, I'd say that your SomeFactory implementation is the best that I would come up with in your case.
If you don't need to use a Builder, and can let Guice create the object based on your fields or constructor parameters, you can code-generate a Factory.
Guice can generate a factory for you through FactoryModuleBuilder, in a feature known as "assisted injection".
Google's other tool, AutoFactory, will code-generate a factory implementation that works in both Guice and Dagger. (It's bundled as "Auto", which includes a model object generator called AutoValue that also generates annotation implementations.)
I put a small demonstration of a child injector and assisted injection in my other SO answer here.
The best approach here is to parameterize the module and pass the parameter through to a provider that you create at runtime:
public class MyModule extends AbstractModule {
private final String code;
public MyModule(String code) {
this.code = code;
}
#Override public void configure() {
Provider<Dep1> depProvider = getProvider(Dep1.class);
bind(SomeService.class)
.toProvider(() -> new SomeService.Builder()
.withApplicationName("Foo")
.withDep(depProvider.get())
.setCode(code)
.build())
.in(RequestScoped.class);
}
}

Multiple implementations to a service using Guice using providers

I need a suggestion for how to code for multiple implementations for a service using Google-guice. Below is the example
TestService testService =new TestServiceImplOne();
TestService testService =new TestServiceImplTwo();
As Guice doesn't allow binding a type to more than one implementations as the below code results in error
binderObject.bind(SomeType.class).to(ImplemenationOne.class);
binderObject.bind(SomeType.class).to(ImplemenationTwo.class);
we can solve this with named annotations as below
binder.bind(Player.class).annotatedWith(Names.named("Good")).to(GoodPlayer.class);
binder.bind(Player.class).annotatedWith(Names.named("Bad")).to(BadPlayer.class);
#Named("Good") Player goodPlayer = (Player)injector.getInstance(Player.class);
#Named("Bad") Player badPlayer = (Player)injector.getInstance(Player.class);
But the application which iam working is something like this. We are binding all the modules in the init() method and creating the injector modules:
//separate method to bind
protected void configure() {
bind(new TypeLiteral<List<Service>>() {}).toInstance(serviceSets);
}
//separate method to inject
Injector i = Guice.createInjector(modules);
But with the above process I can just bind one implementation class to the interface (service class)
Could you please provide me a way to do this with providers. I would like to do something like this below
class TestServiceProvider extends Provider{
// some code where it returns the instance of impl class needed. In my case TestServiceImplOne and TestServiceImplTwo and provider returns the corresponding instance of service class
}
and bind service class with provider class. Something like this
bind(TestService.class).toProvider(TestServiceProvider.class);
I would appreciate if someone suggests a good example using providers or some other way that I can inject whatever implementation I want in the client.
Note: I am using webservices and I am not sure how I can inject different implementations when a webservice is called to a service class.
First of all thanks very much for responding . Coming straight to the point
Iam working on webservices . Heres's the Flow
// GET URI
GET http://www.google.com:8182/indi/provide/organizations/{ou}
OrganizationsResource -------->OrganizationService------>OrganizationServiceImpl
Iam binding OrganizationService with OrganizationServiceImpl and injecting the OrganizationService in OrganizationsResource
#Inject
public void setOrganizationService(OrganizationService orgService) {
this.orgService= orgService;
}
Its fine till here but i have two implementations for OrganizationService ------>OrgDeatilsServiceImpl which does some other job
Now i want to bind both OrganizationServiceImpl and OrgDeatilsServiceImpl to OrganizationService
Confusions:
1) What procedure i have to use in Guice to bind two implementaions?
2) How exactly i can code in OrganizationsResource to dynamically decide which implementation to call.
I would appreciate if you give a sample example for the above requirement.
As Vladimir noted, you can use binding annotations with Providers...
// in YourModule.configure():
bind(TestService.class)
.annotatedWith(Names.named("foo")
.toProvider(TestServiceProvider.class);
...and generic types using TypeLiterals...
bind(new TypeLiteral<List<Service>>() {})
.annotatedWith(Names.named("bar")
.toInstance(serviceSets);
...as long as you ask for an annotated instance using getInstance(Key<T>)...
List<Service> servicesOne = injector.getInstance(
new Key<List<Service>>(Names.named("bar")) {});
// or
List<Service> servicesTwo = injector.getInstance(
Key.get(new TypeLiteral<List<Service>>() {}, Names.named("bar"));
...or, preferably, keep them as fields and let Guice do the injecting, because Guice can't inject local variables. Remember that Guice can only inject classes that it creates, or that you request specifically.
class MyInjectorCreator {
#Inject #Named("foo") Provider<TestService> fooServiceProvider;
#Inject #Named("bar") List<Service> barServices;
// Guice will also wrap/unwrap Providers automatically.
#Inject #Named("foo") TestService fooService;
#Inject #Named("bar") Provider<List<Service>> barServicesProvider;
public void createInjector() {
Injector injector = Guice.createInjector(getListOfModules());
injector.injectMembers(this);
}
}
Now, that answers the question as you phrased it in the title. That said, it sounds like you actually want to choose between implementations at runtime, which is a slightly different but easy-to-solve problem:
class TestServiceProvider extends Provider<TestService> {
// Injection is allowed here!
#Inject ApplicationSettings settings;
#Inject Provider<TestServiceImplOne> oneProvider;
#Inject Provider<TestServiceImplTwo> twoProvider;
#Override public TestService get() {
if (settings.isInTestMode()) {
return new TestTestServiceImplImpl(); // without injection!
} else if (settings.useNewService()) {
return twoProvider.get(); // with injection!
} else {
return oneProvider.get(); // also with injection!
}
}
}
But I should warn you that if you know at injector creation time which service to use, you should probably just bind it correctly then for the sake of code cleanliness and ease of readability:
// in YourModule.configure():
if (settings.isInTestMode()) {
bind(TestService.class).toInstance(new TestTestServiceImplImpl());
} else if (settings.useNewService()) {
bind(TestService.class).to(TestServiceImplTwo.class);
} else {
bind(TestService.class).to(TestServiceImplOne.class);
}

Custom injection with standard annotations

Is it possible to perform custom injection with constructor/factory arguments computed based on injection point WITHOUT defining custom annotation ?
Given a code:
class Foo {
public Foo() {}
public Foo(java.lang.reflect.Field field) {}
}
class Bar {
#javax.inject.Inject Foo foo;
}
How can I configure guice to use second constructor of Foo (passing target field) without modifying Bar.
I know that guice can do custom injections of java.util.logging.Logger with standard #Inject but that seems hardcoded and uses internal api.
You can use injection providers to do it. See https://code.google.com/p/google-guice/wiki/ProviderBindings and https://code.google.com/p/google-guice/wiki/ProvidesMethods. You just have to tell Guice how to instantiate the object when it binds it.
For exemple in a project of mine I tried this :
public static class CalendarServiceProvider implements Provider<CalendarService> {
#Inject
GAppsOAuth oauth;
private GCalendarService service;
#Override
public CalendarService get() {
if (service == null) {
service = new GCalendarService(oauth);
}
return service;
}
}
I don't know if it's what you're looking for, but I hope it'll help.
If you want only to use specific constructor, you can use constructor bindings:
bind(Foo.class).toConstructor(Foo.class.getConstructor(java.lang.reflect.Field.class));
If you need something more complex, you have to use custom injections.

How to select between different CDI-bean implementations runtime

I have a messageListener which purpose is to start clients implementing the Client-interface. The different implementations of the Client-interface is not know at compile time.
The messageListener uses the Launcher-bean to start the clients. So my problem is I need to construct a Launcher-bean that has the selected implementation of the Client-interface injected into it. Im not sure how to do this, or should i approch the problem differently?
public class MyMessageConsumer implements MessageListener {
public void onMessage(Message message) {
String clientType = message.getClientType();
//Here i need to construct a launcher-bean, which has the correct Client-implementation injected
launcher.startClient(message);
}
}
public class Launcher {
#Inject
private Client client;
public void startClient(Message message) {
...
client.start(message);
}
}
edit: I realised that the tricky part is not finding the correct implementation, but that i need the Consumption of a message to happen as a new request. Is it possible to understand what im after?
What you want is a producer.
This way you separate the client of the contextual instance and the producer. So inject them into a producer and have it decide what to use.
For this to be transparent and to avoid ambiguous dependency you could produce a value with #Dynamic qualifier.
#Inject
#Dynamic
Foo foo;
..............................
#Produces
#Dynamic
public Foo getFoo() {
//find out what implementation to use and return it
Creating your own qualifier and producer is very simple to google.

Categories

Resources