Passing state to CDI-container-managed beans - java

I'm using Spring for this project, but I've had the same problem with Guice as well.
Basically, I have functionality that requires both stateless helpers and state data to operate on.
public class AwesomeDoer {
#Inject
private Helper helper; //stateless
...
public void doAwesome(int state) {
helper.help(state)
}
}
This looks pretty good, until doAwesome has 5 parameters and is being called 1000 times, but 3 of the arguments are the same value every time while a fourth argument might change only a handful of times. Changing the appropriate parameters to fields is the obvious solution. However, this requires you to sacrifice either the CDI management of this class, or else you have to have an initializer or setters to fill in the state after Spring does its thing.
I've usually gotten around this by creating a factory managed by Spring, ie
public class AwesomeFactory {
#Inject
private Helper helper;
public AwesomeDoer getAwesomeDoer(int state) {
return new AwesomeDoer(helper, state);
}
}
But again, this means that my AwesomeDoer is no longer being managed by Spring, and it requires me to write yet another layer of non-business logic. It's also easy to imagine this approach leading to the creation of an AwesomeFactoryFactory, etc, which always makes me die a little on the inside.
So does anybody have a cleaner way of doing this?

You can mark your bean using #Configurable from Spring and create it using new AwesomeDoer and passing the parameters in your constructor. #Configurable makes you create the bean on demand and the bean will be managed by Spring to fire the injections like #Autowired.
More info: Create a bean using new keyword and managed by Spring, check the section at the bottom.

Related

Apache Felix - How to guarantee injecting of dynamic references before an activate method

Here is snippet of intrested case:
We have some configuration class it can have multi instances. It suppose that we supply several configurations in one bundle. It's one scope.
#Service
#Component
public class SampleConfigurationImpl implements SampleConfiguration {
// declaration of some properties, init method and etc...
}
Also we have a service which uses these configurations:
#Service
#Component
public class SampleServiceImpl implements SampleService {
#Reference(
referenceInterface = SampleConfiguration.class,
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
policy = ReferencePolicy.DYNAMIC)
private Map<String, SampleConfiguration> sampleConfigurations = new ConcurrentHashMap<>();
private void bindSampleConfigurations(SampleConfiguration sampleConfiguration) {
sampleConfigurations.put(sampleConfiguration.getName(), sampleConfiguration);
}
private void unbindSampleConfigurations(SampleConfiguration sampleConfiguration) {
sampleConfigurations.remove(sampleConfiguration.getName());
}
#Activate
private void init() {
System.out.println(sampleConfigurations.size());
}
}
So, can I get some guarantees that on invocation of init method all configurations are injected (at least of current bundle)? Maybe there is some alternative way to do this. I understand that another bundles can bring new configurations and it's unreal to get guarantees but it's intrested in case of only one bundle.
On practice it can be case when in init method there are only part of configurations. Especially if it's more difficalt case when you have several types of configuration or one service uses another one which has dynamic references and first service relies on fact that everything is injected.
The most unpleasant is that it can bind/unbind configurations both before and after init method.
Maybe there is some way to guarantee that it bind always after init method...
I'm interested in any information. It will be great to get answer on two questions (guarantees before or after). Probably someone has experience how to resolve such problem and can share with me.
Thanks.
No, not that I know of. What I usually do in that case (depending on your use case, it depends on if your activation code is ok with running multiple times) is to create a 'reallyActivate' method I call both from the regular activate and from the bindSampleConfigurations (+ setting an isActivated flag in activate). Then I can perform some logic every time a new SampleConfiguration gets bound, even if it's after the activation. Does that help for your case?

Any differences between 3 ways of dependency injection?

Is the 3rd one most common way to inject a bean? Any differences between them?
Bean constructor parameter injection:
public class Checkout {
private final ShoppingCart cart;
#Inject
public Checkout(ShoppingCart cart) {
this.cart = cart;
}
}
Initializer method parameter injection:
public class Checkout {
private ShoppingCart cart;
#Inject
void setShoppingCart(ShoppingCart cart) {
this.cart = cart;
}
}
Field injection:
public class Checkout {
private #Inject ShoppingCart cart;
}
An opinion-based answer, but it would seem that injecting through the constructor is best for the following reasons.
You can null check in the constructor, which might save you some error handling elsewhere in your class.
You can more easily inject mocks into your class for testing.
You can't forget to supply a dependency.
It doesn't look like magic.
Field injection is probably the most common. The reason is pretty obvious - it's the fastest way to connect things make it do something.
As for differences, there are some:
constructor injection
the only way to access other beans while you initialize this one
otherwise while instantiating beans, your bean field (field injection) will not yet work
example: you need data from other beans while creating this one; based on such data you determine for instance what strategy will this bean use for data storage
field injection
leads to lazy injection of beans (might be Weld specific, not sure now)
means if you don't do any extra work to make it eager, the bean will only actually be accessible once you first invoke a method on it
this is a go-to approach if you "just want the bean"
initializer method parameter injection
you will want this, if you need some extra work done at the moment you inject the bean
this event might happen more than once per bean lifecycle (that's what you have scopes for)
example of usage: you might want to fire an event once the injection happens
All in all, you are free to use any approach. The story here is that there are some use-cases which couldn't be covered by simple field injection.
This is just from the top of my head and is not exhaustive. I hope it sheds some light on the topic.

Guice multibinding-instances get different dependency-instances

I am pretty new to Guice and I am a little bit stuck at the moment.
I am developing the backend for a small game in Java. I want to dynamically inject the game's systems with Guice and I'm using multibinding for that:
private class InstanceModule extends AbstractModule {
#Override
protected void configure() {
bind(GameInstance.class).to(GameInstanceImplementation.class);
bind(EntityManager.class).to(EntityManagerImplementation.class);
bind(EventBus.class).to(EventBusImplementation.class);
bind(MessageBroker.class).toInstance(broker);
Multibinder<GameSystem> systemBinder = Multibinder.newSetBinder(binder(), GameSystem.class);
for (Class<? extends GameSystem> systemClass : systemsConfig) {
systemBinder.addBinding().to(systemClass);
}
}
}
systemsConfig is just a List of Classes of GameSystems I want the game to load.
In my GameInstanceImplementation.class, I inject the used GameSystems like this:
#Inject
public void setSystems(Set<IPMSystem> systems) {
this.systems = systems;
}
And I get the GameInstance like this:
GameInstance instance = injector.getInstance(GameInstance.class);
I am doing it like this, because every GameSystem has different dependencies, some just need the EntityManager, some need the EventBus and so on.
Now it seems that every GameSystem has a different EventBus, EntityManager, etc... so they of course cannot communicate with each other.
I was expecting that every GameSystem gets the same instances of the bound dependencies.
What am I missing here?
Thanks in advance,
Froschfanatika
By default Guice creates a new instance of each dependency every time it's creating an object. If you want to change that behaviour, and get some dependencies shared between objects, then you need to put those dependencies into a different scope.
So, instead of...
bind(EventBus.class).to(EventBusImplementation.class);
you would do something like...
bind(EventBus.class).to(EventBusImplementation.class)
.in(Singleton.class);
then Guice will only every create a single instance of EventBus implementation, and anything which needs an EventBus as a dependency will be given that individual instance.
It's worth noting that Guice's behaviour in this respect is different from Spring's. Spring DI treats all beans as singletons by default. Guice default's is more akin to what Spring calls 'prototype' scope.
https://github.com/google/guice/wiki/Scopes

Injecting components into a POJO using OSGi

I'm new to OSGi and I'm interested in retrofitting some of my jars as OSGi bundles.
However I do not want to introduce additional dependencies to any osgi-specific libraries.
As such annotations are out of the question as are programmatic calls to bundle contexts and what not.
I have found a near match to my requirements in declarative services which allows me to expose my lower level bundles without impacting dependencies however at the higher level (where i actually need to consume the services) i'm still a bit stuck.
I understand that the component xml can be used to declare implementations of services (which i already use for my lower level jars) but also to inject service instances into a specific POJO.
Now my question: how do I get access to the osgi-managed POJO which has the services injected into it? Is it at all possible without introducing new dependencies or do I have to do it programmatically?
If the latter is the case can someone point me in the direction of some code to do it, in other words the component-equivalent of bundleContext.getServiceReference()?
UPDATE
To clarify, if you take the fifth part of this tutorial: http://www.vogella.com/articles/OSGiServices/article.html
He declares a component.xml file which uses reference binding to inject a service into the object QuoteConsumer.
Great, now how do I get an instance of QuoteConsumer that has the necessary services injected into it, I can't very well do "new QuoteConsumer()" right?
UPDATE2
Currently I am registering the instance created by osgi as a static variable which can be requested, I'm thinking this is not the best method especially because I can't set the constructor to private. (the latter would at least result in a true singleton)
Basically the Factory class has:
private void activate() {
instance = this;
}
UPDATE3
A full example of a factory:
public class Factory {
private static Factory instance;
public static Factory getInstance() {
if (instance == null)
instance = new Factory();
return instance;
}
private MyInterface implementation;
public void setMyInterface(MyInterface implementation) {
this.implementation = implementation;
}
public void unsetMyInterface(MyInterface implementation) {
implementation = null;
}
public MyInterface getMyInterface() {
if (implementation == null) {
ServiceLoader<MyInterface> serviceLoader = ServiceLoader.load(MyInterface.class);
Iterator<MyInterface> iterator = serviceLoader.iterator();
if (iterator.hasNext())
implementation = iterator.next();
else
implementation = new MyInterfaceStub();
}
return implementation;
}
#SuppressWarnings("unused")
private void activate() {
instance = this;
}
#SuppressWarnings("unused")
private void deactivate() {
instance = null;
}
}
Any client code can then do:
Factory.getInstance().getMyInterface();
and receive the OSGi loaded service, the SPI loaded one or a stub.
You can still manually set the service instance if necessary.
UPDATE4
To clarify further: this pattern is not meant for applications that are designed from the ground up to be run in an OSGi container but rather for low level libraries that have to run everywhere and even when on an OSGi container must not assume that all consumers are actually using OSGi.
You sound confused ... :-) A service is a replacement for static factories so your factory should not have to exist.
The whole idea of DS is that for each component:
wait until its dependencies are met
create an instance
bind the instance to its dependencies
call activate on the instance
register the instance as a service
So whenever you get a service managed by DS it already is injected (bound) with its dependencies. So as long as you stay with service dependencies you never need static factories ... The whole idea of service is that you do NOT have static factories and can only work with (injected) instances. One of the best parts of OSGi is that you rarely work with factories.
One remark about the requirement not to use annotations. The OSGi annotations are class time only, they do not create a runtime dependency. I strongly suggest to use them since they make services as lightweight as a class and are typesafe in contrast to XML.
One trick to use the annotations and not clutter your code is to create extend your implementation classes that you want to be an OSGi component and add the annotations on this class.
To access a service, you declare a reference to it from another component:
#Reference
public void setFoo(Foo foo) {
this.foo = foo;
}
You might find the Bndtools tutorial will help to clarify the concepts.
I'd say you are on the right track. You can use a static field if it is convenient.
The important thing is that you make the rest of your code deal with the QuoteConsumer appearing and disappearing. So, put in your activator the code to do what you need to do when the QuoteConsumer is available (register it in some field, call some initialization code, I don't know) and put in your deactivate the code you need to indicate that the QuoteConsumer is no longer available.

Using guice for a framework with injected classes, proper way to initialize?

I'm trying to write a framework where arbitrary bean classes are injected with classes from my API, and they can interact with both those classes as well have triggered callbacks based on defined annotations. Here's an example bean:
#Experiment
static class TestExperiment {
private final HITWorker worker;
private final ExperimentLog log;
private final ExperimentController controller;
#Inject
public TestExperiment(
HITWorker worker,
ExperimentLog expLog,
ExperimentController controller
) {
this.worker = worker;
this.expLog = expLog;
this.controller = controller;
}
#SomeCallback
void callMeBack() {
... do something
log.print("I did something");
}
}
I'm trying to use Guice to inject these beans and handle the interdependencies between the injected classes. However, I have two problems:
One of the classes I pass in (HITWorker) is already instantiated. I couldn't see how to move this to a Provider without significantly complicating my code. It is also persistent, but not to the Guice-defined session or request scope, so I am managing it myself for now. (Maybe if the other issues are overcome I can try to put this in a provider.)
More importantly, I need a reference to the other injected classes so I can do appropriate things to them. When Guice injects them, I can't access them because the bean class is arbitrary.
Here's some really bad code for what I basically need to do, which I am sure is violating all the proper dependency injection concepts. Note that hitw is the only instance that I need to pass in, but I'm creating the other dependent objects as well because I need references to them. With this code, I'm basically only using Guice for its reflection code, not its dependency resolution.
private void initExperiment(final HITWorkerImpl hitw, final String expId) {
final ExperimentLogImpl log = new ExperimentLogImpl();
final ExperimentControllerImpl cont = new ExperimentControllerImpl(log, expManager);
// Create an experiment instance with specific binding to this HITWorker
Injector child = injector.createChildInjector(new AbstractModule() {
#Override
protected void configure() {
bind(HITWorker.class).toInstance(hitw);
bind(ExperimentLog.class).toInstance(log);
bind(ExperimentController.class).toInstance(cont);
}
});
Object experimentBean = child.getInstance(expClass);
expManager.processExperiment(expId, experimentBean);
// Initialize controller, which also initializes the log
cont.initialize(expId);
expManager.triggerStart(expId);
tracker.newExperimentStarted(expId, hitw, cont.getStartTime());
}
Am I screwed and just have to write my own injection code, or is there a way to do this properly? Also, should I just forget about constructor injection for these bean classes, since I don't know what they contain exactly anyway? Is there any way to get the dependencies if I am asking Guice to inject the bean instead of doing it myself?
For context, I've been reading the Guice docs and looking at examples for several days about this, to no avail. I don't think I'm a complete programming idiot, but I can't figure out how to do this properly!
Your "experiment" seems to be something like a "request" in the sense that it has a defined lifecycle and some associated stuff the experiment can pull in at will.
Therefore I think you should wrap all that into a custom scope as described in the docs about Custom Scopes. This matches your case in several points:
You can "seed" the scope with some objects (your HITWorker)
The lifecycle: do "enter scope" before you setup the experiment and "exit scope" after you finished your work.
Access to "shared" stuff like ExperimentLog and ExperimentController: Bind them to the scope. Then both the framework and the experiment instance can simple #Inject them and get the same instance.

Categories