How to select between different CDI-bean implementations runtime - java

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.

Related

Getting hk2 and Jersey to inject classes

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.

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

Stateful bean doesn't keep state

I have a stateful bean:
#Stateful
public class ClientContext {
private Band band;
public Band getBand() {
return band;
}
public void setBand(Band band) {
this.band = band;
}
}
I have Arquillian test.
public class RequestTest extends Arquillian {
...
#Inject
private ClientContext context;
#Inject
private RequestProcessor processor;
#Test
public void test() {
context.setBand(new Band());
Assert.assertNotNull(context.getBand());
processor.doSomething();
}
}
And Processor code:
#Stateless
#LocalBean
public class RequestProcessor {
...
#Inject
private ClientContext context;
public void doSomething() {
System.out.println(context.getBand());
}
}
I expect RequestProcessor to print out the Band. But actually I get null every time. What can be wrong or may be I don't understand Stateful beans correctly?
You are answering the question yourself, the main basis about the stateful is the keep just one instance per injection, which will live as long the injecting bean does.
so in you need to share a state between beans, you could use a #SessionBean
To clarify, the #Stateful means one instance are going to be created for each place where you are injecting it, this is useful when you need to bind some actions and their state to ONE component, so, if you need to create some info and then share between other classes you need to pick how you want to share it:
#Singleton: There will be just one instance for the entire app.
#SessionScoped: There will by one instance per client.
#Stateless: Will create one if there is no other available, after it will be release for use of other clients
If you are managing views the you can use too:
#RequestScoped: Will create one instance for each request and then destroys it.
#ViewScoped: The bean will remain as long the client keep making updates within the same view

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

How to avoid using this in a constructor

I have this situation:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class MessageReceiver
{
MessageListener listener;
public MessageReceiver(MessageListener listener, other arguments...)
{
this.listener = listener;
}
loop()
{
Message message = nextMessage();
listener.onMessageReceipt(message);
}
}
and I want to avoid the following pattern: (Using the this in the Client constructor)
class Client implements MessageListener
{
MessageReceiver receiver;
MessageSender sender;
public Client(...)
{
receiver = new MessageReceiver(this, other arguments...);
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
The reason why i need the above functionality is because i want to call the sender inside the onMessageReceipt() function, for example to send a reply. But I dont want to pass the sender into a listener, so the only way I can think of is containing the sender in a class that implements the listener, hence the above resulting Client implementation. Is there a way to achive this without the use of 'this' in the constructor? It feels bizare and i dont like it, since i am passing myself to an object(MessageReceiver) before I am fully constructed. On the other hand, the MessageReceiver is not passed from outside, it is constructed inside, but does this 'purifies' the bizarre pattern?
I am seeking for an alternative or an assurance of some kind that this is safe, or situations on which it might backfire on me.
The Client's dependencies (such as MessageReceiver) could be injected into it rather than having the Client know how to construct the MessageReceiver:
Client client = new Client(...);
MessageReceiver rcvr = new MessageReceiver(client, ...);
client.setMessageReceiver(rcvr);
However I would suggest looking into breaking the circular dependency between these two classes, it sounds as if something is off in your design.
The real reason why passing this to another class in the first class's constructor is a bad practice is because you are allowing a reference to this to escape before it is fully constructed.
It wont backfire on you as long as this is never referenced before construction. However, you should never rely on that assumption. Concurrency is a big factor here, as well as the contract for the code you pass it to.
Since Client is a MessageReceiver, why not make it one?
public Client extends MessageReceiver implements MessageListener{
/* ... */
}
I don't see where the MessageReceiver is used, so at the moment you could write the code without MessageReceiver like this and it would be effectively the same:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class Client implements MessageListener
{
MessageSender sender;
public Client(...)
{
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
I think a standard publish-subscribe or Observer pattern is probably what you need - but it's hard to tell without understanding the subtleties of the problem that you are trying to solve.

Categories

Resources