I have doubts on when to inject the provider of an interface and when to inject an interface directly.
What is the appropriate situation where a provider should be used? Please give examples.
If the scope of an interface is #Dependant, then the injector will create a new object anyway, if so then do we still need to use a provider?
If #New is used, a new object is created. Do we need a provider then?
One of the main reasons to use providers (you don't inject providers though) is to do some configuration of a class. Another good reason is if the class isn't available as a CDI bean.
Related
What I need is to get new instance of service every time when some consumer needs this service + using CDI. I've read a lot of articles and I can't find the answer to 2 my questions.
If we use factories, why in service consumer we call factory (http://www.rpgnextgen.com/wiki/doku.php?id=component_factory ) and after that we get reference to service. I mean
// get factory
ComponentFactory factory = (ComponentFactory) context.getService(serviceReferences[0]);
// get instance
ComponentInstance instance = factory.newInstance(null);
Is there no way to set factory with certain interface and in service consumer call service when osgi inside calls the factory?
If in service consumer we call factory then why we mark service as component when de facto factory is component?
The problem is that without factory I do #Inject #OsgiService (javase) or#OSGiService (javaee) and I can use different filters and code is very clear. Using component factory I (as I understand) loose this ability.
ComponentFactory exists for consumers that want to use a factory, because they want to control the lifecycle of the individual components. For example, if they want to create an instance of the component for every web request.
If you don't want to use ComponentFactory... then don't.
I need for every consumer new instance of component.
I haven't tried yet, but according to the documentation when using PAX-CDI and an OSGi v6 container then the prototype scope should do what you need:
#OsgiServiceProvider
#PrototypeScoped
public class MyService implements SomeService{
OSGi services in are special types of beans in CDI. Compare them to EJBs, you can use CDI to inject references to the different types of EJBs, but the components will have their own lifecycle. The same goes for OSGi services; their life cycle is not controlled by CDI. CDI just injects references to those services.
This means CDI factories can't be used with OSGi services. Just like you can't use CDI factories with EJBs. There is not really a way to create an OSGi service instance per injection point, so there's no workaround either.
If you require this kind of model: You have to create a factory mechanism yourself.
I'm a new Guice user, having been a long-time user of Spring IoC. I have a number of #Singleton classes for my service tier, which I understand is roughly equivalent to Spring's default bean scope.
However, when I am using #Inject in my Wicket pages a CGLib proxy of the target objects is created each time the page is constructed, thus creating new instances of my supposed-singletons.
Note that I'm injecting concrete classes, not interfaces.
How can I use #Inject and retrieve the single singleton instance of my Guice-injected objects?
Updated: Solution as per Sven's accepted answer
Inject interfaces in Wicket components rather than concrete classes. Despite much discussion on the subject in the linked thread, this appear to be the only practical solution.
The following issue gives some background:
https://issues.apache.org/jira/browse/WICKET-1130
How would you implement Spring like annotation based JMX feature. If class is marked by #ManagedResource methods of the class marked with #ManagedOperation are automatically exposed via JMX.
I would like to avoid creating interfaces with MBean notation. I'm using Play with Guice framework. The naive approach first comes to mind:
Iterate over all classes managed by Guice
If class is marked with annotation, create new interface which fits MBean notation. Amend class, amended class should implement new created interface.
Register instance of the class in MBean server.
Second step will be done using byte code manipulation tool, for example ASM. Is it possible to do it with ASM ? How would you implement such feature ?
Technically, you don't need an interface. MBeans are entirely described by metadata. You can implement your own custom implementation of DynamicMBean which returns the appropriate description of your management "interface" (without actually creating said interface). no crazy byte code manipulation necessary, just basic reflection.
I have sucessfully used Guice to Inject Providers into the servlet portion of an existing java web application, however, I can't access the injectors through the business layer (non-servlet java classes) of the application.
I have read up on Injecting the Injector, but to me that seems more like a hack and in several places, including the Guice documentation, it says not to do that too much.
I guess my question is, Where do I bootstrap a java web app so that the non-servlet/filter classes have access to the injector created in the class I use to extend GuiceServletContextListener? Is there any way to make those classes injectable without injecting the injector?
Thank you and let me know if you need any clarification.
Edit:
I am attempting to do this with a simple logger, so far, in my
servlets, I call:
#Inject
private static org.slf4j.Logger log;
The injection is set up in MyLoggerModule as follows (which is in the
createInjector call with ServletModule) :
#Override
public void configure() {
bindListener(Matchers.any(), new SLF4JTypeListener()); // I
built my own SLF4JTypeListener...
}
This all works perfectly in the servlets, but the field injection does
not work when called by a class that is not a servlet or filter.
Guice doesn't intercept calls for new objects, so if your business layer isn't already using Guice to create the objects that need injection, it'll need modification to do so.
The injection only works when handled by Guice during injection. So starting from the base injector you've made, whatever is marked with #Inject which is needed for the instance you've requested will be provided by Guice as best it can, and in turn, during instanciation of those, further #Inject annotations will be filled in by providers and bindings until nothing new needs to be instanciated. From that point on however you are not going to get fields injected into servlets created outside Guice's injection, perhaps by calling new somewhere, which is likely what your Object Factory is doing.
You'll need to change your Object Factory to use providers instead of new. If you could edit these, it wouldn't be too hard to do since Guice can give you default providers for bindings.
So one way your business layer could be Guice aware is to have whatever is creating servlets first create an Injector and then request the servlets be created by the injector. If this means you'll have more than one injector, then yes, that will be a problem but only for the objects you want to be singletons. So you could make a factory pattern class for a singleton injector, or you could find where these classes (here typed bar) which are creating servlets themselves are created (in foo), and then start with the injector there (in foo) using one Guice injector to create those (bar type) classes and also modifying them (bar type) to request a provider for the servlets which they'll use instead of making calls for a new servlet.
Now that I think about this, it could be simple if it kind of only happens once or twice for 10-20 servlet types, or it could be complicated if there's some framework that defines totally flexible behavior for what gets newed up when and why.
Another option would be avoiding #Inject on fields at all times, as recommended. So now your servlets are taking in an org.slf4j.Logger as a construction parameter. The constructor is marked #Inject, and it assigns the parameter's value to the field. Then any place you're not using injection should break with an incorrect number of parameters at a new call. Fix these by figuring out how to either get the servlet provided here instead, or how to get a provider for the servlet into the class.
Not sure what you mean... if you inject objects in to your servlets/filters, those objects have their dependencies injected by Guice as well, and so on all the way down.
How are you creating the classes that you're trying to inject this logger in to? They must be created by Guice to be injected, which means no new.
Say I have a ClassWithManyDependencies. I want to write a Guice Provider for this class, in order to create a fresh instance of the class several times in my program (another class will depend on this Provider and use it at several points to create new instances).
One way to achieve this is by having the Provider depend on all the dependencies of ClassWithManyDependencies. This is quite ugly.
Is there a better way to achieve this?
Note - I certainly don't want the Provider to depend on the injector. Another option I considered is having ClassWithManyDependencies and ClassWithManyDependenciesProvider extend the same base class, but it's butt ugly.
As mentioned on the mailing list, anywhere you can inject ClassWithManyDependencies you can simply inject Provider<ClassWithManyDependencies> instead, no need to write anything special yourself. Guice does this for you.
You shouldn't have to write a provider except to integrate with other frameworks.
Just DON'T bind your ClassWithManyDependencies in scope SINGLETON and in the class that wants to build many instances, instead of having a ClassWithManyDependencies instance injected you have a Provider injected. (Guice can do that for free for every binded class)
On this provider you can just call get(), if not in scope SINGLETON it makes a fresh new instance each time.
Now if you are in the tricky case that ClassWithManyDependencies relies both on some GUICE IOC and on some constructor parameters, then you shall go for Assisted Injections