Guice multiple annotations - java

I have an interface called StatsStore. I have 2 implementations of this store. An in-memory and an SQL implementation called InMemoryStatsStore and SqlStatsStore. In order to inject them I've create 2 annotations #InMemoryStore and #SqlStore. the injections are:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.to(InMemoryStatsStore.class);
bind(StatsStore.class)
.annotatedWith(SqlStore.class)
.to(SqlStatsStore.class);
Now I want to add a new layer of annotation to separate between InMemoryStringStore and InMemoryNumberStore but I can't add more than one annotation to the binding lines e.g. the following does not compile:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.annotatedWith(NumberStoreAnnotation.class) // using named doesn't work as well
.to(InMemoryNumberStore.class);
How can I add more than one annotation without using a single named one which would be quite complicated the more layers I add to it?
The other solution I had in mind is Injecting twice:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.to(InMemoryStatsStore.class);
bind(InMemoryStatsStore.class)
.annotatedWith(NumberStoreAnnotation.class)
.to(InMemoryNumberStore.class);
Thanks all.

As Amit said, you can't have more than one #BindingAnnotation apply to any given injection. Internally, Guice works like a Map<Key, Provider> where a Key is a possibly-parameterized class with an optional single annotation instance. However, because these are instances, you're welcome to create your own instantiable annotation that works the way Named works.
#Inject #InMemoryStore(NUMBER) StatsStore inMemoryNumberStore;
#Inject #SqlStore(STRING) StatsStore sqlStringStore;
// or
#Inject #Store(dataType=NUMBER, backend=SQL) sqlNumberStore;
The annotation must have the fields defined like so. (If you have one element named value, you can omit the property name per JLS 9.7.3.) Equal annotations are defined as in the Annotation.equals docs.
public enum DataType { NUMBER, STRING; }
public enum Backend { SQL, IN_MEMORY; }
#BindingAnnotation #Retention(SOURCE) #Target({ FIELD, PARAMETER, METHOD })
public #interface Store {
DataType dataType();
Backend backend();
}
That works nicely for #Provides, when you can invoke the annotation the same way you inject it, but how can you create a factory method for instances like Names.named? For that, you'll need to do one of the following:
Create an anonymous implementation, with accessors for each attribute as well as correct implementations of equals and hashCode. Note that the hashCode contract is much stricter than for Object, but you can get compatible implementations from Apache annotation utils or similar libraries.
Use AnnotationLiteral, which provides equals and hashCode implementations for arbitrary subclasses.
Use Google Auto or a similar code generator to generate code for a compatible implementation for you. Familiarity with this type of solution is particularly useful for Android and other memory-constrained environments for which reflection is slow, though such environments usually preclude you from using Guice. (#Qualifier annotations work the same way in other JSR-330 compatible dependency injection frameworks, though, including Dagger.)
If the above seems a little complicated, or if you want more complex logic than Guice's map-based implementation can accomplish, one alternative is to add a layer of indirection that you control:
public class StoreStore {
#Inject Provider<InMemoryNumberStore> inMemoryNumberStoreProvider;
// ...
// You can also inject the Injector to call getInstance with a class literal.
public StatsStore getStore(DataType dataType, Backend backend) {
// This can also be a switch or any other sort of lookup, of course.
if (dataType == NUMBER && backend == IN_MEMORY) {
return inMemoryNumberStoreProvider.get();
} // ...
}
}

You can't do that:
#BindingAnnotation tells Guice that this is a binding annotation. Guice will produce an error if ever multiple binding annotations apply to the same member.
You could use named bindings instead, or you should consider redesigning your solution.

Related

Avoiding default interface implementation for #Bean

Let's say
I have integration tests, therefore there is an ApplicationContextIntegrationTests class that contains dummy beans (dependencies on other services) for initializing the app context for integration profile like this:
#Bean
public MyService myService(Proc proc) {
return new MyServiceImp();
}
I have an interface MyInterfaceA with 20 methods (the code is autogenerated based on the definition in api.yaml), I cannot implement it and I don't have access to the implementation. This interface (well, it is an implementation) also should be inserted in the application context. Obviously, I need to implement all interface methods in order to insert that bean and it leads to messy code with default methods implementations on 50 lines. Moreover, I need to insert 3 interfaces.
Is there a way to avoid that huge amount of code?
I have found that Lombok provides a #Delegate annotation which is used in similar situations, but it is appliable only on fields, whereas I need to deal with methods (bcs of #Bean).
Is this generated class that implements MyInterfaceA also a bean? If so, you can use #MockBean to mock its implementation in the test. This way, wherever a bean of type MyInterfaceA is used, the mock will be injected in its place, and you can have the mock do whatever you want.

Is it better to have multiple nested classes with the same dependency or one with a larger scope?

In my Spring boot app i'm creating a Factory for creating different objects with the same interface and dependency like below.
#Component
public class FarmFactory {
#Autowired
private FarmRepo farmRepo;
public IFarm create(FarmType type) {
if (type == type.APPLE) {
return new AppleFarm(farmRepo);
} else if (type == type.ANIMAL) {
return new AnimalFarm(farmRepo);
} else {
return new EmptyFarm(farmRepo);
}
}
}
I was wondering if it was better to limit the scope the FarmRepo dependency by instead injecting it into each subclass of farm (apple, animal, empty). Or if it was better to keep a single dependency in a higher scope of the Factory.
Alternatively the dependency FarmRepo could be passed into the create method with the type, but not sure what the rule of thumb is for dependency scope.
According to my experience, a good design can reduce if-else as much as possible. So I prefer to injecting it into each subclass in your case. Thus in future, you have more flexibility if the dependency also have subclass as well.
I suggest to create named beans of your real implementations (AppleFarm, AnimalFarm ..) and inject the FarmRepo. With you factory your real implementations won't be managed by Spring (no beans).
#Component("appleFarm")
#RequiredArgsConstructor <- this is a Lombok feature check it out
public class AppleFarm implements Farm {
private final FarmRepo repo;
...
}
I assume your IFarm implementations are model classes. It is not a good practise to have a repository inside a model. You should consider to move the creation of different IFarm implementations to the FarmRepo.
If IFarm implementations are some sort of service classes that governs business logic then you should let spring handle it injecting the FarmRepo instance to them. In that case you better consider having an abstract class rather than using IFarm, because FarmRepo is a common dependency among them.
There is nothing wrong in employing a simple factory method to instantiate the required runtime type, if that's required, it needs to be done somewhere, it helps you gain a valid design in terms of OCP (open close principle) preventing you to change bahaviour depending on type parameter, rather you make use of polymorphism.

Java annotation example in official docs

While reading the Oracle documentation on annotations (quite new to this concept), I came across the following snippet in the beginning (link at the bottom). I am not clear on what the example is illustrating. Is the public #interface definition an enhanced version of a normal interface definition? id(), engineer() etc are methods that return default values if not specified in the interface implementation? But then the instantiation is confusing, is it providing an implementation of an interface where id() returns 2868724 etc? Also not clear what the function travelThroughTime() is for. Any clarifications appreciated:
/**
* Describes the Request-For-Enhancement(RFE) that led
* to the presence of the annotated API element.
*/
public #interface RequestForEnhancement {
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";
}
#RequestForEnhancement(
id = 2868724,
synopsis = "Enable time-travel",
engineer = "Mr. Peabody",
date = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
http://docs.oracle.com/javase/1.5.0/docs/guide/language/annotations.html
To break down your questions:
Is #interface just an enhancement of interface?:
No, #interface is declaring something quite different from a standard interface- you are essentially declaring an annotation type. Making this declaration enables the declared thing to be used as an annotation in other code. So the declaration:
public #interface RequestForEnhancement
enables the annotation #RequestForEnhancement to be used in later code.
An annotation describes metadata for a method or a class. The #RequestForEnhancement annotation, for example, might be placed in front of a method in another class to indicate that some developer wants that method to be changed in some way.
Declaring an interface, by contrast, is declaring the signature of a group of functions. Classes which later implement an interface must then provide implementations of those functions.
What are the "methods" (synopsis(), engineer(), etc.) in the annotation body for? These are not really methods like you would be used to seeing in a class or interface definition. Instead, these represent fields that the annotation you've just declared has. A #RequestForEnhancement annotation on a method should indicate what the requested change to the method is, and possibly who is expected to implement the enhancement to the method. Thus the fields synopsis and engineer are fields that can be included in the annotation.
What does this section mean?:
#RequestForEnhancement(
id = 2868724,
synopsis = "Enable time-travel",
engineer = "Mr. Peabody",
date = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }
This is an example of using the annotation that we've declared in the block starting with #RequestForEnhancement. Usages like this will likely occur all over your codebase, in many different classes, once the annotation has been defined. In this particular example, there is a method travelThroughTime(Date destination) in some class which apparently doesn't work very well. Some developer coming across the method thought it should be improved by making it do what it appears to claim to do (travel through time). That developer decided to reflect his request by putting an #RequestForEnhancement annotation on the method with some information about when the request was made, who was expected to make the enhancement, etc.
Sure, but how do you use the contents of an annotation for anything useful? (A question I'll ask for you :-) )
So let's say I want to write a tool which looks through all of my code for methods annotated with #RequestForEnhancement and send an e-mail to the engineers listed in the request, along with information about the annotation and the request for enhancement. How would I get started?
The basic mechanism to find out what methods have an annotation and the way to get values from the annotation is through Java reflection. A tutorial which includes an example of annotations and reflection is here (it's actually a good tutorial on annotations in general).
So sure, you can use reflection to get info out of these annotations, but when would you run a tool to use the info from the annotations? (another one I'll ask for you) Java provides the ability for you to define annotation processors which use annotation information when your code is compiled. Here's what looks like a reasonable tutorial. You can also use the information in your annotations at runtime. If you've ever used JavaFX, for example, you may have noticed that annotations can affect runtime behavior (adding #FXML to a field helps JavaFX fill that field with a value defined in your fxml).

Can I use CDI to look for all qualifier-annotated methods in any beans?

I'd like to implement a pattern for my business logic similar to the way WebSocket-annotated methods are handled. Given the value of a particular parameter of an incoming message, I'd like to invoke an annotated method in a managed bean that is looked up on the fly. For example, given the following setup:
#Qualifier
#Target( ElementType.METHOD )
#Retention( RetentionPolicy.RUNTIME )
public #interface Handler { }
#ApplicationScoped public class MyHandler1 {
#Handler public void someMethod() { }
#Handler public void otherMethod() { }
}
Then I'd like to write a function to pick a method based on that parameter value. It should be as simple as given "someMethod" as a value and looking up my qualified managed beans with a method named "someMethod" and calling it.
My problem is that selecting beans with Instance<...> only works on type-level qualifiers and/or types. To actually find the methods I would need to iterate through all the methods. I'm a little worried about the cost of lookup and/or having to manage a cache or some sort.
You shouldn't use a qualifier to mark methods, any other annotation would do.
Then you can write a CDI extension observing the ProcessAnnotatedType event, if you do want to use CDI.
Having said that, from your problem description, I'm not really sure what exactly you're trying to do or whether CDI would be the best way to do it.
You can use https://code.google.com/p/reflections/ to scan your classes. It is quite fast and can easily be cached. You can even use a reflections maven plugin to do the scan on compile time ...

Can someone explain what com.google.inject does?

I've seen a class declared with its only constructor being annotated with #Inject.
And I don't see the one constructor being called anywhere in the entire project.
So two questions:
<1> What does #Inject mean? (What does it do? Why is the constructor being annotated with it?)
<2> As mentioned, the constructor never gets called directly, does that have anything to do with the fact that it is annotated with #Inject?
Google Guice is a dependency injection library that allows you to construct objects simply by declaring relationships between them. Objects are constructed as they are demanded to construct other objects. You can also implement abstract classes or interfaces with different implementations by configuring Guice, which makes it very useful for running or testing your code.
#Inject annotates constructors and methods that determine what an object needs to be initialized. There are also a lot of other annotations that determine how Guice works. But simply annotating objects isn't enough; you also have to configure them with Guice bindings.
Here's a really simple example (from one of my applications). I have a MySQLDataTracker that requires a MysqlConnectionPoolDataSource:
public class MySQLDataTracker extends ExperimentDataTracker {
#Inject
public MySQLDataTracker(MysqlConnectionPoolDataSource ds) {
....
}
}
Note that MySQLDataTracker extends ExperimentDataTracker, an abstract class that can be implemented several ways. In my Guice bindings I declare that
bind(ExperimentDataTracker.class).to(MySQLDataTracker.class);
This declares that whenever I want an ExperimentDataTracker, a MySQLDataTracker will be constructed. I also need to make sure that the requisite object for constructing this is available, so I declare a provider:
#Provides #Singleton
MysqlConnectionPoolDataSource getMysqlCPDS() {
return (some thingy I construct...);
}
This says that there should only be a single connection pool data source. It also means that when I try to get an instance of ExperimentDataTracker, Guice has everything it needs to construct it. If I didn't have the above, it would throw an error.
ExperimentDataTracker tracker = injector.getInstance(ExperimentDataTracker.class);
However, it doesn't stop here. Other things depend on the ExperimentDataTracker, so it's used in turn to inject other objects. At the top level of my code there is actually only one call to getInstance, which makes Guice construct pretty much everything. I don't have to write the new statement anywhere.
I'm a big fan of Guice after seeing how it reduced the need for me to initialize a bunch of objects in order to initialize other objects. Basically I just ask for the object I want, and poof! it appears.

Categories

Resources