I have used the standard factory pattern method before to create instances of classes (implementing a specific interface) using a Factory class, which has a "create" method, that returns the right instance based on the parameter passed to it (example snippet given below):
public class SimpleFactory {
public static SimpleObjectInterface getSimpleObject(int data) {
SimpleObjectInterface toReturn;
switch(data) {
case 1:
toReturn = new OneSimpleObject();
break;
case 2:
toReturn = new TwoSimpleObject();
break;
default:
toReturn = new DefaultSimpleObject();
break;
}
return toReturn;
}
}
Now I am using Guice in my project for dependency injection. My question is how can I achieve something like the above using Guice? Which implementation instance is needed is decided at runtime based on some user input.
I have looked at Provider and #Named annotations. But I don't understand how exactly it will help me.
In general for the problem where you want a factory that injects most dependencies, but still allows some client-supplied deps, you would use Factories by Assisted Injection.
However in your case this would lead to conditional logic in your factory, which is probably not ideal (it is explicitly discouraged in Guice modules).
I think for your situation a MapBinder would be ideal, and you wouldn't need a factory at all, since you're only switching on data type and not building anything really. In your module you configure a map of int (in your case) keys to impls of SimpleObjectInterface. Then in your main runtime class you inject the map, and when you need an instance of a simple object and have int data available, you call get(data) on the injected map.
I don't have an IDE on this machine, so I can't test the code, but from memory it would be something like below:
In your module:
public class MyModule extends AbstractModule {
protected void configure() {
MapBinder<Integer, SimpleObjectInterface> mapbinder
= MapBinder.newMapBinder(binder(), Integer.class, SimpleObjectInterface.class);
mapbinder.addBinding(1).toClass(OneSimpleObject.class);
mapbinder.addBinding(2).toClass(TwoSimpleObject.class);
}
}
In your app code:
#Inject
private Map<Integer, SimpleObjectInterface> simpleObjectMap;
...
void applicationCode() {
...
Integer data = getData();
SimpleObjectInterface simpleObject = simpleObjectMap.get(data);
...
}
Only issue here is you can't have the "default" binding that you had in your switch statement. Not sure of the best way to handle that, maybe you could assign a default impl in your app code if the object is still null after trying to instantiate it from the map binder. Or you could go back to assisted inject with conditional logic, but it's not really "assisted" injection if the sole dependency is client supplied.
See also: Can Guice automatically create instances of different classes based on a parameter?
Related
I want to conduct a chain of processing elements and wire them together via Guice. Let's assume the following path:
interface A implemented by class AImpl needs some input
interface B implemented by class BImpl needs A
interface C implemented by class CImpl needs B
interface D implemented by class DImpl needs C
The dependency of A can only be resolved at runtime and not at configuration time. The usual approach would be to use Assisted Injection in this case to create a factory, that takes the missing instances as parameters, just like this:
public interface AFactory {
public A createA(String input);
}
But what I actually want is something like this:
public interface DFactory {
public D createD(String inputForA);
}
I don't want to manually pass AImpl-specific dependencies through the whole hierarchy.
Is it possible to achieve this with Guice? If not, what's the best way to circumvent this problem elegantly while still retaining benefits of injection?
Cheating way: Stick input in a static variable or singleton ThreadLocal. Set it before your pipeline starts and clear it after it ends. Bind everything else through DI.
Fancy way: In A, refer to a #PipelineInput String inputString but don't bind it in your main injector. Otherwise, bind dependencies as you normally would, including referring to #PipelineInput in other pipeline-related classes. When you do need a D, get it from your implementation of a DFactory, which I'm calling PipelineRunner.
public class PipelineRunner {
#Inject Injector injector; // rarely a good idea, but necessary here
public D createD(final String inputForA) {
Module module = new AbstractModule() {
#Override public void configure() {
bindConstant(inputForA).annotatedWith(PipelineInput.class);
}
};
return injector.createChildInjector(new PipelineModule(), module)
.getInstance(D.class);
}
}
Naturally, binding attempts for A, B, C, and D will fail outside of PipelineRunner for lack of a #PipelineInput String--you'll get a CreationException when you create the injector with those unsatisfied dependencies, as you discovered--but those pipeline-based dependencies should be easy to separate into a Module that you install into the child injector.
If this feels too hacky, remember that PrivateModules are also "implemented using parent injectors", and that the whole point of dependency injection is to make a dependency like inputForA available to the whole object graph in a decoupled way.
I see three options. They depend on how often you change the input for A .
1) Bind input as a constant in your module. This works only, if you know that value before you create the Injector and never want to change the value. See bindConstant
2) Use a private submodule which binds either A or the value for input inside that module. Basically you can have two or three instance graphs with different value. See newPrivateBinder.
3) Use a Scope ala RequestScope, SessionScope, ... This way you can change the input often but you must enter/leave the scope at some point to be defined. See Custom Scopes for an example.
I am working on a project where I am using MyBatis annotations as persistence framework. Therefore, I have to create an interface for the 'mapper' and compose the mapper in the service like :
class XYZServiceImpl{
public XYZMapper getXYZMapper(){
return SessionUtil.getSqlSession().getMapper(XYZMapper.class)
}
}
Now while unit testing the service with Mockito, I am trying to inject a mock for the mapper. But since I am injecting mock in an instance of XYZService, how can mock a method of the service itself, in this case getXYZMapper() is what I am trying to stub. Although I have got a solution of creating the instance XYZMapper in the service and not call on demand like the above code does something like :
Class XYZServiceImpl{
XYZMapper mapper;
public void useXYZMapper(){
mapper = SessionUtil.getSqlSession().getMapper(XYZMapper.class);
}
}
But that would bring a lot of code changes (ofcourse I can refactor) but is there a way to achieve without having to make code changes?
Also what would be a 'purist' way to have a mapper instance in the class is it the method 1 that is better than method 2 in terms of performance?
EDIT : Here XYZMapper is an interface. Something like :
public interface XYZMapper{
#Select("SELECT * FROM someclass WHERE id = #{id}")
public SomeClass getSomeClass(int id);
}
EDIT : I am facing a similar situation but with a variance that I have a service that I do want to test like XYZServiceImpl. Now it has a method getXYZDetails() which has a lot of business logic handled within the service. Now if getXYZDetails looks like the following :
public XYZDetails getXYZDetails(int id){
XYZDetails details = new XYZDetails();
details.set1Details(fetchSet1Details(id));
//Perform some business logic
details.set2Details(fetchSet2Details(id));
if(details.set2Details() != null){
for(int i = 0; i < details.set2Details().size(); i++){
flushTheseDetails(i);
}
}
.
.
}
Kindly notice that fetchSet1Details(), fetchSet2Details(), flushTheseDetails are public service, public and private service respectively.
I want to know of a method that can mock/stub these methods while testing getXYZDetails() thus enabling me to
There are several options you can use.
Inject dependency
This works only for simple methods like getXYZMapper when method only returns external dependency of you object. This may require to create new XYZServiceImpl instances if for example mapper is bound to connection which is opened per request.
Encapsulate method behavior in object
Another way to achieve similar result is to use a factory or service locator
like this:
public class XYZServiceImpl {
public XYZServiceImpl(XYZMapperFactory mapperFactory) {
this.mapperFactory = mapperFactory;
}
public XYZMapper getXYZMapper() {
return mapperFactory.getMapper();
}
}
This will allow you easily substitute factory in test with implementation which returns mock mapper.
The similar approach can be used for other methods fetchSet1Details, fetchSet2Details, flushTheseDetails that is moving them to other class or classes. If the method contains complex (and may be loosely related) logic it is a good candidate to be moved in separate class. Think about what these methods do. Usually you can move some essential and unrelated part of them to other class or classes and this makes mocking them much easier.
Subclass
This is not recommended but in legacy code sometimes is very helpful as a temporary solution.
In your test subclass you class under test and override methods you need:
#Test
public void someTest() {
XYZServiceImpl sut = new XYZServiceImpl() {
public XYZMapper getXYZMapper() {
return mapperMock;
}
public Whatever fetchSet1Details() {
return whateverYouNeedInTest;
}
}
sut.invokeMethodUnderTest();
}
The only thing you may need to do is to change access modifier of private method to package-private or protected so you can override them.
Spying
This method in also discouraged but you can use mockito spies:
XYZServiceImpl realService = new XYZServiceImpl();
XYZServiceImpl spy = Mockito.spy(realService);
when(spy.fetchSet1Details()).thenReturn(whaeveryouneed);
when(spy.getXYZMapper()).thenReturn(mockMapper);
spy.methodUnderTest();
I would suggest the "purist" way of doing this is to accept an XYZMapper instance in your constructor and store it in a local field.
In production use, you can pass an e.g. SQLXYZMapper, which will interact with your database. In test use, you can pass in a mocked object that you can verify interactions with.
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.
I often need a client bundle and some i18n-ed messages in presenters and views.
I would like to know which is the best way to get them : Injection or Singleton?
Solution 1: Up to now, I used to get the messages using a Singleton :
public interface MyMessages extends Messages{
String key1();
String key2();
...
class Instance {
private static MyMessages instance = null;
public static MyMessages getInstance() {
if (instance == null) {
instance = GWT.create(MyMessages.class);
}
return instance;
}
}
}
FooView.java :
MyMessages.Instance.getInstance().key1();
Solution 2: Would it be better to get it with an injection like this ?
private MyMessages i18n;
#Inject
public FooView(MyMessages i18n){
this.i18n=i18n;
}
The second solution seems cleaner to me but I sometimes get stuck when I need a non-empty constructor which uses some i18n strings:
#Inject
private MyMessages i18n;
public Bar(Foo foo){
/*
* do something which absolutely requires i18n here.
* The problem is that injectable attributes are called
* after the constructor so i18n is null here.
*/
foobar();
}
First, client bundles and I18N messages, while not singleton themselves, share their state with all their instances, so that once compiled to JavaScript and optimized by the compiler it's as if they were singletons. There are a few corner-case (IIRC, when using the WithLookup variants of I18N interfaces) but generally speaking it doesn't buy you anything explicitly treating them as singletons.
So the question basically becomes whether to use GWT.create() explicitly or have the instance injected. I'd say it's a matter of taste, but also technically GWT.create() doesn't play nice with non-GWTTestCase unit-tests.
Finally, as for your latest question, I suppose that by "non-null constructor" you mean that it takes values that aren't dependencies (i.e. value objects); in which case you should probably use assisted-injection rather than constructing the object yourself and then injecting its members (as an aside: how are you injecting the members then?)
Maybe I am just blind, but I do not see how to use Guice (just starting with it) to replace the new call in this method:
public boolean myMethod(String anInputValue) {
Processor proc = new ProcessorImpl(anInputValue);
return proc.isEnabled();
}
For testing there might be a different implementation of the Processor, so I'd like to avoid the new call and in the course of that get rid of the dependency on the implementation.
If my class could just remember an instance of Processor I could inject it via the constructor, but as the Processors are designed to be immutable I need a new one every time.
How would I go about and achieve that with Guice (2.0) ?
There is some time since I used Guice now, but I remember something called "assisted injection". It allows you to define a factory method where some parameters are supplied and some are injected. Instead of injecting the Processor you inject a processor factory, that has a factory method that takes the anInputValue parameter.
I point you to the javadoc of the FactoryProvider. I believe it should be usable for you.
You can get the effect you want by injecting a "Provider", which can by asked at runtime to give you a Processor. Providers provide a way to defer the construction of an object until requested.
They're covered in the Guice Docs here and here.
The provider will look something like
public class ProcessorProvider implements Provider<Processor> {
public Processor get() {
// construct and return a Processor
}
}
Since Providers are constructed and injected by Guice, they can themselves have bits injected.
Your code will look something like
#Inject
public MyClass(ProcessorProvider processorProvider) {
this.processorProvider = processorProvider;
}
public boolean myMethod(String anInputValue) {
return processorProvider.get().isEnabled(anInputValue);
}
Does your Processor need access to anInputValue for its entire lifecycle? If not, could the value be passed in for the method call you're using, something like:
#Inject
public MyClass(Processor processor) {
this.processor = processor;
}
public boolean myMethod(String anInputValue) {
return processor.isEnabled(anInputValue);
}