How to collect several interfaces into a Collection in HK2? - java

I have my AbstractBinder and I bind several classes with the same interface. Let's say I bind Fish and Cat which both implement Animal interface.
What is the easiest/proper way of injecting them into a bean which takes Collection<Animal> ?
PS: Spring has equivalent in simply #Autowire List<Animal> and the collection is created and populated by Spring.

HK2 has IterableProvider<T>, as mentioned here in the documentation. You can get the service by name, by qualifier annotation, or just iterate over them, as it's an Iterable. Just for fun, here is a test.
public class IterableProviderTest {
public static interface Service {}
public static class ServiceOne implements Service {}
#QualAnno
public static class ServiceTwo implements Service {}
#Qualifier
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public static #interface QualAnno {
public static class Instance
extends AnnotationLiteral<QualAnno> implements QualAnno {
public static QualAnno get() {
return new Instance();
}
}
}
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bind(ServiceOne.class).to(Service.class).named("one");
bind(ServiceTwo.class).to(Service.class).qualifiedBy(QualAnno.Instance.get());
}
}
#Inject
private IterableProvider<Service> services;
#Test
public void test_IterableProvider() {
ServiceLocator locator = ServiceLocatorUtilities.bind(new Binder());
locator.inject(IterableProviderTest.this);
assertEquals(2, services.getSize());
Service serviceOne = services.named("one").get();
assertTrue(serviceOne instanceof ServiceOne);
Service serviceTwo = services.qualifiedWith(QualAnno.Instance.get()).get();
assertTrue(serviceTwo instanceof ServiceTwo);
}
}
UPDATE
For a List<Service> (to avoid HK2 InterablProvider), the only think I can think of is to use a Factory and inject the IterableProvider into it, and from there return the list. For example
public class Binder extends AbstractBinder {
#Override
protected void configure() {
...
bindFactory(ListServiceFactory.class).to(new TypeLiteral<List<Service>>(){});
}
}
public static class ListServiceFactory implements Factory<List<Service>> {
#Inject
private IterableProvider<Service> services;
#Override
public List<Service> provide() {
return Lists.newArrayList(services);
}
#Override
public void dispose(List<Service> t) {}
}
Yeah it's a little bit of extra work.

In the latest release of hk2 (2.4.0) you can
#Inject Iterable<Foo> foos;
That allows you to keep your pojo's without any hk2 API in them.
For more information see: Iterable Injection

Related

How to inject bean via generic variable in spring

I have problem with injecting bean with generic types. Look at the example. I will inject to the service a repository which types takes from App class. Now i have exception:
No qualifying bean of type 'asd.IRepository' available: expected single matching bean but found 2: a,b
asd here is package, just for tests.
What can I do in this situation? Is any way to makes it?
public interface IRepository<T, V> {
void print();
}
#Component
public class A implements IRepository<String,String> {
#Override
public void print() {
System.out.println("A");
}
}
#Component
public class B implements IRepository<Double,String> {
#Override
public void print() {
System.out.println("A");
}
}
#Service
public class ServiceABC<V, T> {
#Autowired
private IRepository<V,T> repo;
public void print(){
repo.print();
}
}
#Controller
public class App {
#Autowired
private ServiceABC<String, String> serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print();
}
It looks like you don't know in advance which implementation of your IRepository interface you will need. And you will know that at runtime. In this case it is a typical case for Factory pattern where you will have a IRepositoryFactory that will have a method thhat retrieves specific implementation by type (for example IRepositoryFactory.getInstance(String type); So in your ServiceABC you may use the IRepository to get specific bean at runtime. So Factory pattern may be an answer to your question. I also wrote an article that deals with this type of problem and proposes the idea of self-populating Factory (using Open source library that provides such utility). Here is the link to the article: Non-intrusive access to "Orphaned" Beans in Spring framework
You have to name your components and autowire by name:
#Component("A")
public class A implements IRepository<String,String> {...}
#Component("B")
public class B implements IRepository<Double,String> {...}
[...]
#Autowired
#Qualifier("B")
private IRepository repo;
Something like that?
#Controller
public class RepositoryFactory {
#Autowired
private IRepository<String, String> a;
#Autowired
private IRepository<Double, String> b;
public IRepository getRepository(String className) {
if(className.equalsIgnoreCase("a")) {
return a;
} else if(className.equalsIgnoreCase("b")) {
return b;
}
return null;
}
}
#Service
public class ServiceABC {
#Autowired
private RepositoryFactory repositoryFactory;
public void print(String className){
repositoryFactory.getRepository(className).print();
}
}
#Controller
public class App {
#Autowired
private ServiceABC serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print(A.class.getSimpleName());
}
}s

One interface multipe implementations. How get the right one at runtime

Lets say I have an Object with one boolean field.
public class AnyPojo {
private boolean b;
}
An interface DoAnything
public interface DoAnything {
void doAnything();
}
And two #Service annotated implementations of DoAnything
public class DoAnythingOneImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
public class DoAnythingTwoImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
In another #Service class the boolean field of AnyPojo determines which implementation of DoAnything should be called. How can I achive that? I can use ApplicationContext here and make the decision like below. But not sure if there are better ways.
#Service
public class AnotherServiceImpl implements AnotherService {
#Autowire
private ApplicationContext context;
#Override
public void anotherDoing(AnyPojo anyPojo) {
if(anyPojo.getB()){
context.getBean(DoAnythingOneImpl.class).doAnything();
} else{
context.getBean(DoAnythingTwoImpl.class).doAnything();
}
}
First things first, if your class requires particular implementations, why don't you simply inject these classes?
If you have several implementations of an interface, you have to inform Spring framework which one you would like to inject into a class. You can distinguish implementations by their unique bean names:
#Service("oneImpl")
public class DoAnythingOneImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
#Service("twoImpl")
public class DoAnythingTwoImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
And then inject both instances to the client service by marking which implementation should by assign to particular fields:
#Service
public class AnotherServiceImpl implements AnotherService {
#Autowire
#Qualifier("oneImpl")
private DoAnything doAnythingOneImpl;
#Autowire
#Qualifier("twoImpl")
private DoAnything doAnythingTwoImpl;
#Override
public void anotherDoing(AnyPojo anyPojo) {
if(anyPojo){
doAnythingOneImpl.doAnything();
} else{
doAnythingTwoImpl.doAnything();
}
}
Note that I would not call a service component from another service component to make sure I avoid potential redundant cycle in the future.
I would keep the following flow :
Controller ---canCall---> Services ---canCall---> Repositories
And if you need services with a more complex logic, then introduces the concept of Facade
Controller ---canCall---> Facades ---canCall---> Services ---canCall---> Repositories
However, here is a solution :
#Service("myServiceOne")
public class DoAnythingOneImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
#Service("myServiceTwo")
public class DoAnythingTwoImpl implements DoAnything {
#Override
public void doAnything(){
//..
}
}
You can autowire both services and choose the best one based on your boolean :
#Service
public class AnotherServiceImpl implements AnotherService {
#Autowired
#Qualifier("myServiceOne")
private DoAnything serviceOne;
#Autowired
#Qualifier("myServiceTwo")
private DoAnything serviceTwo;
#Override
public void anotherDoing(AnyPojo anyPojo) {
if(anyPojo){
serviceOne.doAnything();
} else{
serviceTwo.doAnything();
}
}
}

How to Inject implementation in Guice 4.0

I had this class as follows which works fine
#Singleton
public class EmpResource {
private EmpService empService;
#Inject
public EmpResource(EmpService empService) {
this.empService=empService;
}
}
public class EmpService {
public void getName(){..}
}
Now instead of using EmpService directly, I had to create an interface and EmpService implement that interface as follows.
public interface IEmpService{
void getName();
}
public class EmpServiceImpl implements IEmpService {
public void getName(){...}
}
So now my resource class has to use the interface but I am not sure how to reference the implementation it has to use.
#Singleton
public class EmpResource {
private IEmpService empService;
#Inject
public EmpResource(IEmpService empService) {
this.empService=empService;
}
}
I've seen this and I wasn't sure where my binding should go. (This is my first project related to Guice so I am a total newbie).
This is the error that came "No implementation for com.api.EmpService was bound." which is totally understandable but not sure how to fix it.
I appericiate your help.
FYI: I am using Dropwizard application.
You would configure your module similar to this:
public class YourModule extends AbstractModule {
#Override
protected void configure() {
bind(EmpService.class).to(EmpServiceImpl.class);
// ....
}
}
you also have to add a Provide Methode for your EmpServiceImpl class
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(IEmpService.class).to(EmpServiceImpl.class);
}
#Provides
EmpServiceImpl provideEmpServiceImpl() {
// create your Implementation here ... eg.
return new EmpServiceImpl();
}
}

Java Bean Composite injection

I have an interface
public interface Abstraction {
void execute();
}
I have built a composite implementation and want to registered this object as the bean, #Named
#Named
public class Composite implements Abstraction {
private List<Abstraction> list;
#Inject
public Composite(List<Abstraction> list) {
this.list = list;
}
public void execute() {
list.forEach(Abstraction::execute);
}
}
How do I set it up so that the set of implementations to the abstraction gets injected properly into the Composite above? I will be having another object that takes the abstraction as a dependency and I want it to receive the #Named Composite above with the 2 Implementations below injected into the ctor.
public class Implementation1 implements Abstraction {
public void execute() { }
}
public class Implementation2 implements Abstraction {
public void execute() { }
}
If you create a bean for each of your implementations, your example will work out of the box. For example, annotate your implementations with #Named or #Component and mark them for scanning (component scan their package)
#Configuration
#ComponentScan
public class StackOverflow {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(StackOverflow.class);
System.out.println(ctx.getBean(Composite.class).list);
}
}
interface Abstraction {
void execute();
}
#Named
class Composite implements Abstraction {
List<Abstraction> list;
#Inject
public Composite(List<Abstraction> list) {
this.list = list;
}
public void execute() {
list.forEach(Abstraction::execute);
}
}
#Named
class Implementation1 implements Abstraction {
public void execute() {
}
}
#Named
class Implementation2 implements Abstraction {
public void execute() {
}
}
The Composite's list will contain both implementations.
Alternatively, since you only have two implementations, you could name their beans and inject them separately. For example
#Component("one")
class Implementation1 implements Abstraction {
public void execute() {
}
}
#Component("two")
class Implementation2 implements Abstraction {
public void execute() {
}
}
and inject them in the Composite
List<Abstraction> list = new ArrayList<>(2);
#Inject
public Composite(#Qualifier("one") Abstraction one, #Qualifier("two") Abstraction two) {
list.add(one);
list.add(two);
}
I suggest this solution just because the order of initialization of Abstraction beans might mess up your context initialization. For example if Implementation1 somehow depended on the initialization of Composite, the context would complain. This is rare and you can control it in other ways. Still, being explicit about the beans might be clearer in this case.

Injecting method interceptors in Guice

I've searched all over the web for it and everyone (including) google suggests using requestInjection() but I still don't understand how to use it. I have a class that implements Method Interceptor:
public class CacheInterceptor implements MethodInterceptor {
private ILocalStore localStore;
private IRemoteStore remoteStore;
private CacheUtils cacheUtils;
public CacheInterceptor() {
}
#Inject
public CacheInterceptor(ILocalStore localStore, CacheUtils cacheUtils, IRemoteStore remoteStore) {
this.localStore = localStore;
this.cacheUtils = cacheUtils;
this.remoteStore = remoteStore;
}
}
And I have 3 classes that extends AbstractModule.
public class CacheUtilModule extends AbstractModule {
#Override
protected void configure() {
bind(CacheUtils.class);
}
}
public class LocalCachingModule extends AbstractModule {
#Override
public void configure() {
bind(ILocalStore.class).to(LocalStore.class);
}
}
public class RedisCachingModule extends AbstractModule {
#Override
protected void configure() {
bind(IRemoteStore.class).to(RemoteStore.class);
}
}
And I did the following for binding the interceptor
public class RequestScopedCachingModule extends AbstractModule {
#Override
public void configure() {
install(new CacheUtilModule());
install(new LocalCachingModule());
install(new RedisCachingModule());
MethodInterceptor interceptor = new CacheInterceptor();
requestInjection(interceptor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Cacheable.class),
interceptor);
}
}
So basically, I want to inject the localStore, remoteStore, and cacheUtils in my MethodInterceptor with my own implementation mapped out in my 3 modules. But this didn't work. I guess I am just confused with requestInjection(). In the documentation, requestInjection does this
Upon successful creation, the Injector will inject instance fields and methods of the given object.
But where do we specify the mapping between the interface and the implementation class? How can I get what I wanted to do to work?
requestInjection will only inject fields and methods - it won't invoke the constructor and doesn't know anything about the #Inject annotations on your constructor. If you add #Inject to all of your fields your code should work as you expect.

Categories