I have a class (OmeletteMaker) that contains an injected field (Vegetable). I would like to write a producer that instantiates an injected object of this class. If I use 'new', the result will not use injection. If I try to use a WeldContainer, I get an exception, since OmeletteMaker is #Alternative. Is there a third way to achieve this?
Here is my code:
#Alternative
public class OmeletteMaker implements EggMaker {
#Inject
Vegetable vegetable;
#Override
public String toString() {
return "Omelette: " + vegetable;
}
}
a vegetable for injection:
public class Tomato implements Vegetable {
#Override
public String toString() {
return "Tomato";
}
}
main file
public class CafeteriaMainApp {
public static WeldContainer container = new Weld().initialize();
public static void main(String[] args) {
Restaurant restaurant = (Restaurant) container.instance().select(Restaurant.class).get();
System.out.println(restaurant);
}
#Produces
public EggMaker eggMakerGenerator() {
return new OmeletteMaker();
}
}
The result I get is "Restaurant: Omelette: null", While I'd like to get "Restaurant: Omelette: Tomato"
If you provide OmeletteMaker yourself, its fields will not be injected by the CDI container. To use #Alternative, don't forget specifying it in the beans.xml and let the container instantiate the EggMaker instance:
<alternatives>
<class>your.package.path.OmeletteMaker</class>
</alternatives>
If you only want to implement this with Producer method then my answer may be inappropriate. I don't think it is possible (with standard CDI). The docs says: Producer methods provide a way to inject objects that are not beans, objects whose values may vary at runtime, and objects that require custom initialization.
Thanks Kukeltje for pointing to the other CDI question in comment:
With CDI extensions like Deltaspike, it is possible to inject the fields into an object created with new, simply with BeanProvider#injectFileds. I tested this myself:
#Produces
public EggMaker eggMakerProducer() {
EggMaker eggMaker = new OmeletteMaker();
BeanProvider.injectFields(eggMaker);
return eggMaker;
}
Related
I'm relatively new to Guice, and some things still give me a pretty hard time.
My particular question is, how do you handle nested injections in Guice.
Example:
Class A uses Class B via #Inject, and Class B uses Class C.
Explicitly:
My Module where I bind to Providers.
public class ModuleBinder extends AbstractModule {
#Override
protected void configure() {
bind(DatabaseControllerInterface.class)
.toProvider(DatabaseControllerProvider.class).asEagerSingleton();
bind(AnalyzerInterface.class)
.toProvider(AnalyzerProvider.class).asEagerSingleton();
bind(SystemAdministrationInterface.class)
.toProvider(SystemAdministrationProvider.class).asEagerSingleton();
bind(LogInServiceInterface.class)
.toProvider(LogInServiceProvider.class);
}
}
The DatabaseControllerProvider:
public class DatabaseControllerProvider implements Provider<DatabaseControllerInterface> {
#Override
public DatabaseControllerInterface get() {
return new DatabaseControllerImpl();
}
}
The LogInServiceProvider:
public class LogInServiceProvider implements Provider<LogInServiceInterface> {
#Override
public LogInServiceInterface get() {
return new LogInServiceImpl();
}
}
And finally, the LogInService uses:
public class LogInServiceImpl implements LogInServiceInterface{
#Inject
private DatabaseControllerProvider databaseControllerProvider;
private final DatabaseControllerInterface databaseController;
public LogInServiceImpl() {
this.databaseController = databaseControllerProvider.get();
}
#Override
public User register(final String mail, final String userName, final String password) {
databaseController.registerUser(userName, mail, password, UserRole.ADMIN);
}
}
The call is then:
public class Test() {
public static test() {
final Injector injector = Guice.createInjector(new ModuleBinder());
logInService = injector.getInstance(LogInServiceInterface.class);
logInService.registerUser("test", "test", "test");
}
}
I know most of you guys will get sick with that code, but hey, I'm a beginner with Guice, so please be gentle with me.
I want to use Constructor injection, I already realized that field injection is considered "evil". Do you have any idea how to get that working by keeping the providers (I need them)?
Using the injections in the example does nothing on the "second" level, the DatabaseControllerImpl in LogInServiceImpl is null.
Did I configure something wrong? Did I misunderstand the usage of Provides and/or Modules?
I hope somebody can and wants to help me. If you need more informations, post a comment.
With best regards,
JosefRucksack
Your direct answer: You're calling new T(); in your Providers, which doesn't support field injection.
First, a real timesaver: Don't keep your explicit Providers. If you have bound a T, Guice allows you to inject a Provider or call Injector.getProvider for that T, even if you haven't explicitly created a Provider yourself. See the Built-In Bindings page on the wiki,
or the Injector docs (emphasis mine):
Contains several default bindings:
This Injector instance itself
A Provider<T> for each binding of type T
The Logger for the class being injected
The Stage in which the Injector was created
Instead, do it this way:
public class ModuleBinder extends AbstractModule {
#Override
protected void configure() {
bind(DatabaseControllerInterface.class)
.to(DatabaseControllerImpl.class).asEagerSingleton();
bind(AnalyzerInterface.class)
.to(AnalyzerImpl.class).asEagerSingleton();
bind(SystemAdministrationInterface.class)
.to(SystemAdministrationImpl.class).asEagerSingleton();
bind(LogInServiceInterface.class)
.to(LogInServiceImpl.class);
}
}
You then have the same choice you do now, to inject T or Provider<T> and call getInstance or getProvider as needed.
If your Providers are absolutely necessary, especially if they actually receive an instance from some other system or service locator, one other option is to add your #Inject fields into them as in the Provider bindings wiki page and pass them into your constructor, or to just inject a MembersInjector<T>:
public class LogInServiceProvider implements Provider<LogInServiceInterface> {
#Inject MembersInjector<LogInServiceImpl> logInServiceImplInjector;
#Override
public LogInServiceInterface get() {
LogInServiceImpl logInServiceImpl = YourExternalDep.getLogInService();
logInServiceImplInjector.injectMembers(logInServiceImpl);
return logInServiceImpl;
}
}
However, this explicit-Provider solution is not idiomatic Guice, and should only be used with external or legacy code. Guice's whole reason for existence is to automate away boilerplate and let your systems come together clearly and flexibly. Providers are an implementation detail; let Guice create them for you.
The various #EnableXXXRepository annotations of Spring Data allow you to specify a custom base class for your repositories, which will be used as an implementation of methods in your repository.
If such a base class needs access to other beans in the ApplicationContext how does one get those injected? It doesn't work out of the box, because Spring Data instantiates those base classes itself, supporting only special store dependent constructor parameters.
Note: I created this answer in the chat to this now deleted question and thought it might be valuable for others, although the original question is gone.
In the #Enable...Repository annotation specify a repositoryBaseClass and repositoryFactoryBeanClass. Like this:
#EnableMongoRepositories(
repositoryBaseClass = MyBaseClass.class,
repositoryFactoryBeanClass = MyRepositoryFactoryBean.class)
In that RepositoryFactoryBean class, you can use normal dependency injection, because it is a Spring Bean, so, for example, you can get an instance of SomeBean injected via the constructor, as shown below:
public class MyRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends MongoRepositoryFactoryBean<T,S,ID>{
private final SomeBean bean;
public MyRepositoryFactoryBean(Class repositoryInterface, SomeBean bean) {
super(repositoryInterface);
this.bean = bean;
}
}
Your RepositoryFactoryBean now create an instance of a custom RepositoryFactory by overwriting 'getFactoryInstance'.
#Override
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new MyMongoRepositoryFactory(operations, bean);
}
While doing so, it can pass on the bean to be injected. bean in the example above.
And this factory finally instantiates your repository base class. Probably the best way to do it is to delegate everything to the existing factory class and just add injecting of the dependency to the mix:
public class MyMongoRepositoryFactory extends MongoRepositoryFactory {
private final SomeBean bean;
MyMongoRepositoryFactory(MongoOperations mongoOperations, SomeBean bean) {
super(mongoOperations);
this.bean = bean;
}
#Override
protected Object getTargetRepository(RepositoryInformation information) {
Object targetRepository = super.getTargetRepository(information);
if (targetRepository instanceof MyBaseClass) {
((MyBaseClass) targetRepository).setSomeBean(bean);
}
return targetRepository;
}
}
There is a complete working example on Github.
In my JSF application I'm using a #ViewScoped bean Publication to show/edit data coming from my database. In that bean there is a field for a subtype-specific data object, i.e. containing a different object depending on whether the publication is, say, a book or an article.
#ViewScoped
#Named
public class Publication implements Serializable {
#Inject
DatabaseStorage storage;
...
String id;
String type;
PublicationType typedStuff;
#PostConstruct
public void init() {
// Get an URL parameter from the request,
// look up row in database accordingly, initialize String "type".
switch (type) {
case "ARTICLE":
typedStuff = new Article(id);
break;
case "BOOK":
typedStuff = new Book(id);
break;
default:
break;
}
}
}
...with classes Article and Book that implement / extend PublicationType.
So far, so good, but I would like for typedStuff to be a CDI bean, so that I can inject useful resources there.
I've read this and this page on producer methods, as well as this tutorial and this very related SO question, but none of them answer precisely my question: Can I inject based on a field that the injecting bean itself only knows at runtime?
I've gotten the producer method to work as such, but I can't parametrize it, so I can't get that switch to work.
If I put the producer method in a separate class (or bean) then I don't have access to the type field.
If I inject the injecting bean into the producer class, or move the producer method into the injecting class, I get a circular injection.
If I put the producer method statically into the injecting class, I also don't have access, because type cannot be static. (Although, since it's only used momentarily...?)
Also (and that is probably the answer right there), the producer method is executed before my injecting bean's init method, so type wouldn't even have been set yet.
Does anybody have a better idea?
No you cannot, but you can select a bean based on the field value. Say:
public interface PublicationType {}
#PType("ARTICLE")
public class Article implements PublicationType{}
#PType("BOOK")
public class Book implements PublicationType {}
And define a qualifier:
public #interface PType {
String value();
}
And define an AnnotationLiteral:
public class PTypeLiteral extends AnnotationLiteral<PType> implements PType {}
Then you can use:
public class Publication {
#Any
#Inject
private Instance<PublicationType> publicationTypes;
public void doSomething() {
PType ptype = new PTypeLiteral(type);
// Of course you will have to handle all the kind of exceptions here.
PublicationType publicationType = publicationTypes.select(ptype).get();
}
}
There is the javax.inject.Provider interface (I think You are using #Named and #Inject annotations from the same package).
You could use it to achieve what You want. It will create instances for You with injected fields.
One drawback is that You will have to set the id yourself.
#ViewScoped
#Named
public class Publication implements Serializable {
#Inject
DatabaseStorage storage;
#Inject
Provider<Article> articleProvider;
#Inject
Provider<Book> bookProvider;
String id;
String type;
PublicationType typedStuff;
#PostConstruct
public void init() {
// Get an URL parameter from the request,
// look up row in database accordingly, initialize String "type".
switch (type) {
case "ARTICLE":
typedStuff = articleProvider.get();
typedStuff.setId(id);
break;
case "BOOK":
typedStuff = bookProvider.get();
typedStuff.setId(id);
break;
default:
break;
}
}
}
I would like to have a static instance method with Guice for one of the components (non-managed bean should be able to access this class). I created something like this:
public class LookupService {
#Inject
private static Provider<Injector> injector = null;
private final ILookup<IWS> lookup;
#Inject
public LookupService(ILookup<IWS> lookup) {
this.lookup = lookup;
}
public static LookupService instance() {
return injector.get().getInstance(LookupService.class);
}
public <T extends IWS> T lookup(Class<T> localInterface) {
return lookup.lookup(localInterface);
}
}
What do you think about this design ? Any other ideas on this ? (accessing managed beans from non-managed objects)
Basically, the pattern you're looking for is called "requesting static injection" and there's a Binder method dedicated to it. Once you have that down, your code looks a lot like this example from the Guice docs.
public class MainModule extends AbstractModule {
#Override public void configure() {
requestStaticInjection(LookupService.class);
}
}
public class LookupService {
/** This will be set as soon as the injector is created. */
#Inject
static Provider<LookupService> provider = null;
private final ILookup<IWS> lookup;
#Inject
public LookupService(ILookup<IWS> lookup) {
this.lookup = lookup;
}
public static LookupService instance() {
return provider.get();
}
public <T extends IWS> T lookup(Class<T> localInterface) {
return lookup.lookup(localInterface);
}
}
A few notes:
While you can still set your field to be private, remember that this means you cannot set it in tests (or in future non-Guice usage) without Guice's private-field-access magic. When using injected fields, we often make them package-private and then put the tests in the same package.
Static injection is generally seen as something to endorse only when migrating to Guice, or when you use other code you can't change. When possible, try to avoid global state--even if this means making FooBean data-only and creating an injected FooBeanService.
Even though you can inject an Injector wherever you'd like, you might find it easier to test if you simply inject a Provider<LookupService> instead. Only inject an Injector if you don't know what type you're going to need until runtime--for example, if you implement LookupService.lookup(...) using an Injector by passing the class literal to the injector to get an instance.
In fact, it's hard to say from here, but ILookup seems to act a lot like the Service Locator pattern, which solves the exact type of problem that Guice solves with dependency injection! If that's the case, you might as well rewrite ILookup to use Guice: Just remove calls to LookupService.instance().lookup(Foo.class) and instead create a matching pair of #Inject static Provider<Foo> fooProvider and requestStaticInjection(FooUser.class).
Hope that helps!
I have a command class that needs to have 2 constructors. However,
using structuremap it seems that I can only specify one constructor to
be used. I have solved the problem for now by subtyping the specific
command class, which each implementation implementing it's own
interface and constructor. Like the code below shows. The
ISelectCommand implements two separate interfaces for the
string constructor and the int constructor, just for the sake of
registering the two subtypes using structuremap.
However, I consider this a hack and I just wonder why is it not
possible for structuremap to resolve the constructor signature by the
type passed in as parameter for the constructor? Then I could register
the SelectProductCommand as an ISelectCommand and
instantiate it like:
ObjectFactury.With(10).Use>();
orObjectFactury.With("testproduct").Use>();
public class SelectProductCommand : ISelectCommand<IProduct>,
ICommand, IExecutable
{
private readonly Func<Product, Boolean> _selector;
private IEnumerable<IProduct> _resultList;
public SelectProductCommand(Func<Product, Boolean> selector)
{
_selector = selector;
}
public IEnumerable<IProduct> Result
{
get { return _resultList; }
}
public void Execute(GenFormDataContext context)
{
_resultList = GetProductRepository().Fetch(context,
_selector);
}
private Repository<IProduct, Product> GetProductRepository()
{
return ObjectFactory.GetInstance<Repository<IProduct,
Product>>();
}
}
public class SelectProductIntCommand: SelectProductCommand
{
public SelectProductIntCommand(Int32 id): base(x =>
x.ProductId == id) {}
}
public class SelectProductStringCommand: SelectProductCommand
{
public SelectProductStringCommand(String name): base(x =>
x.ProductName.Contains(name)) {}
}
P.s. I know how to tell structuremap what constructor map to use, but my again my question is if there is a way to have structuremap select the right constructor based on the parameter passed to the constructor (i.e. using regular method overloading).
The short answer is this post by the creator of Structuremap.
The long answer is regarding the structure you have in that piece of code. In my view, a command is by definition a "class" that does something to an "entity", i.e it modifies the class somehow. Think CreateNewProductCommand.
Here you are using commands for querying, if I'm not mistaken. You also have a bit of a separation of concern issue floating around here. The command posted defines what to do and how to do it, which is to much and you get that kind of Service location you're using in
private Repository<IProduct, Product> GetProductRepository()
{
return ObjectFactory.GetInstance<Repository<IProduct, Product>>();
}
The way I'd structure commands is to use CreateProductCommand as a data contract, i.e it only contains data such as product information.
Then you have a CreateProductCommandHandler which implements IHandles<CreateProductCommand> with a single method Handle or Execute. That way you get better separation of concern and testability.
As for the querying part, just use your repositores directly in your controller/presenter, alternatively use the Query Object pattern
I think I solved the problem using a small utility class. This class gets the concrete type from ObjectFactory and uses this type to construct the instance according to the parameters past into the factory method. Now on the 'client' side I use ObjectFactory to create an instance of CommandFactory. The implementation of CommandFactory is in another solution and thus the 'client solution' remains independent of the 'server' solution.
public class CommandFactory
{
public ICommand Create<T>()
{
return Create<T>(new object[] {});
}
public ICommand Create<T>(object arg1)
{
return Create<T>(new[] {arg1});
}
public ICommand Create<T>(object arg1, object arg2)
{
return Create<T>(new[] {arg1, arg2});
}
public ICommand Create<T>(object arg1, object arg2, object arg3)
{
return Create<T>(new[] {arg1, arg2, arg3});
}
public ICommand Create<T>(object[] arguments)
{
return (ICommand)Activator.CreateInstance(GetRegisteredType<T>(), arguments);
}
public static Type GetRegisteredType<T>()
{
return ObjectFactory.Model.DefaultTypeFor(typeof (T));
}
}