Is there any way to provide a dynamic binding at runtime? AbstractBinder allows you to bind a factory but the class type has to be known at compile time.
Something to the effect of:
public class MyDynamicBinder implements DynamicBinder {
#Override
public boolean canBind(Class<?> someContract) {
return iCanBindThis(someContract);
}
#Override
public Object bind(Class<?> someContract) {
return getMyInstance(someContract);
}
}
hk2 is an extremely dynamic injection container. Unlike guice and CDI it can add services to its ServiceLocator at any time (if you have appropriate privilege). With the ServiceLocator (which is a service available anywhere you have any other hk2 service) then you can use the methods in ServiceLocatorUtilities like addClasses or addOneDescriptor in order to add whatever services you need at any time at all. You can also remove services at any time, but few people ever do that (unless you are writing a dynamic container of your own)
Related
I am looking to do some refactoring of a Java J2EE application, but I am not clear how to have CDI provide the needed dependencies:
The current setup is quite simple/easy to understand:
#ApplicationScoped
public class MyApplication {
#Inject
#Named("Default")
private Dependency dependency;
public void dostuff(){
dependency.process();
}
}
I now need a new instance of dependency each time I call dostuff.
I am unclear on how to use CDI to create this for me. My Dependency has its own dependencies that I would like CDI to create for me.
I expect there is a layer of indirection I need to add.
Additional context:
This class is part of a process that polls for work to be done, and is hosted in Wildfly.
We are not using Spring in the project.
Since what you desire is having a new instance of Dependency, each time the method is called, I think what you need is an instance of Provider that is (javax.inject.Provider<T>) injected in your class/bean.
Inject the provider to your current class:
#Inject Provider<DesiredBean> provider;
Then, in your method doStuff() obtain the new instance:
DesiredBean desiredBean = provider.get();
This should get you going.
Is there a specific reason you need to use CDI besides the dependency injection?
If not, I'd suggest making doStuff() take a Dependency object as a parameter:
public void doStuff(Dependency dependency) {
dependency.process();
}
Then, when you call the method, you provide it with a new instance of Dependency:
myApplication.doStuff(new Dependency());
That way, you are still keeping your class less coupled than declaring a new instance in the constructor or field.
I have a standard Magnolia module that I've implemented as a Spring MVC REST client. In this module, I am trying to retrieve a JCR node and use Node2BeanProcessor to transform the Node object into my custom bean. Code below:
#Repository
public class JcrRepo() {
#Inject
public Node2BeanProcessor node2Bean;
public MagicWord getMagicWord(String key) {
Session session = LifeTimeJCRSessionUtil.getSession("magic");
Node theNode = session.getNode("/magicWords/" + key);
return node2Bean.toBean(theNode, MagicWord.class);
}
}
When I run this, I encounter a NullPointerException for the variable node2Bean. Which means it wasn't injected properly. However, I am able to do this:
node2Bean = Components.getComponent(Node2BeanProcessor.class);
The Components.getComponent() javadoc states: "Returns a component from the currently set ComponentProvider. Consider using IoC to inject the component instead." Which is what I'm trying to figure out.
Note that I have not done any Guice configuration as I'm looking for a way to leverage on Magnolia's already initialized Guice context to grab my objects.
Is there a better way to do injection than this, or have I done anything wrong or skipped a step?
Appreciate the help.
P.S. For now I've implemented a hacky way to use this in Spring IoC:
#Bean
public Node2BeanProcessor node2Bean() {
return Components.getComponent(Node2BeanProcessor.class);
}
(Working with Magnolia 4.5) I use #Inject for Node2BeanProcessor in a class implementing info.magnolia.module.ModuleLifecycle:
public class MyModule implements ModuleLifecycle {
#Inject
private Node2BeanProcessor node2BeanProcessor;
#Override
public void start(ModuleLifecycleContext moduleLifecycleContext) {
...
getNode2BeanProcessor().toBean(someNode);
...
}
}
Maybe your NullPointerException comes from theNode? Have you verified that theNode is not null?
Another guess is that it could be a lifecycle issue. From what I remember, Components.getComponent() works in situations where #Inject does not (in Magnolia).
Finally: Your instance variable should definitely be private.
If JcrRepo is not instantiated by Guice then Guice also won't be available to inject the Node2BeanProcessor field. Mixing Spring and Guice IoC containers can get confusing, so I tend to stick with Guice as that's what comes with Magnolia.
I want to use Guice to produce instances (actually singletons/single instances for the module/dependency injection context), but have some of the managed instances being wrapped in a proxy.
The idea behind this is to add a synchronization layer around a few items which deal with "one at a time" resources. The only solution I've come up with is to create two Injectors.
Given the code below,
public class ApplicationContext {
private Injector injector;
public <T> T get(Class<? extends T> cls) {
return injector.getInstance(cls);
}
public ApplicationContext() {
injector = Guice.createInjector(new Module() {
binder.bind(InterfaceOne.class).to(ImplementationOne.class);
binder.bind(InterfaceTwo.class).to(ImplementationTwo.class);
binder.bind(InterfaceThree.class).to(ImplementationThree.class);
});
}
}
}
where ImplementationThree depends on InterfaceTwo, and ImplementationTwo in turn depends on InterfaceOne.
What I want now, is that after ImplementationTwo is instantiated, I want to wrap it in a Proxy before it's injected into ImplementationThree. So:
I want to use Guice to have ImplementationOne being injected into ImplementationTwo
Before ImplementationTwo is injected into ImplementationThree, I want to wrap it.
What I'd love to see, is a Guice interceptor that is invoked after the instantiation and injection of dependencies, but before it's handed over to the injector context.
I could use a Provider for ImplementationTwo, but then I don't know how to get an instance of InterfaceOne from Guice.
The Provider method can also use injection. Try
#Inject #Provides
public InterfaceTwo provideInterfaceTwo(InterfaceOne i){
return InterfaceTwoImplementation
}
Why not use plain old Guice AOP support? Something like
#SynchronizedAccess
public void foo(...){
...
}
this way you can see just by looking at the code that there is something more to the method.
If you absolutely want to wrap things in a Proxy:
If you only have a few classes to proxy, then #acerberus suggestions works fine.
To automate, you can use a #afterInjection, part of Custom Injections, and reassign the field to your proxy using reflection.
I find it a bit archaic to program using locks while we have things like akka around but YMMV.
I have a web service (JAX-RPC) that runs on application server (Websphere Application Server 7.0).
Normally the development process looks like this:
I write a class with web service implementation (e.g. MyService.java)
The IDE generates web service endpoint interface (e.g. MyService_SEI.java)
The IDE generates configuration XMLs
When the web service is deployed, MyService_SEI is the declared service interface and the application server instantiates a MyService instance by means of the public no-arg constructor.
But what if I want to do constructor injection (i.e. have MyService class without a no-arg constructor) or if I want to provide a dynamic proxy object which implements MyService_SEI and use that?
Is there a way I can take control of the instantiation procedure (like a filter or interceptor) to achieve this?
You can't do constructor injection as Injection always occur after the default constructor is called. If you try to use an injected reference inside the default constructor it will ALWAYS fail, there's no workaround for this as this is mandate by the specification.
So the first option you mentioned is discarded.
For the second option, using a filter or interceptor, you actually have an option. WebSphere WebServices are build using Axis2 implementation and Axis provide a way of implementing Handlers.
You can add handlers into the JAX-WS runtime environment to perform additional processing of request and response messages.
Here's a handler example, from Axis documentation:
package org.apache.samples.handlersample;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SampleProtocolHandler implements
javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
public void close(MessageContext messagecontext) {
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext messagecontext) {
return true;
}
public boolean handleMessage(SOAPMessageContext messagecontext) {
Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
// Include your steps for the outbound flow.
}
return true;
}
}
And than you add a handler.xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chain name="MyHandlerChain">
<jws:protocol-bindings>##SOAP11_HTTP ##ANOTHER_BINDING</jws:protocol-bindings>
<jws:port-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:MySampl*</jws:port-name-pattern>
<jws:service-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:*</jws:service-name-pattern>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
</jws:handler-chain>
an easy method would be to make two classes. one your class with all the bells and whistles (constructor injection etc lets call it worker). and the actual service. the service would delegate what it needs to the worker class, who it can get by calling some factory method.
The factory can even look at some common db or other config to decide which run time instance (which class, what config, shared or common) so you have good separation and power
Just cause you are using one framework/ method of injection does not mean you cannot mix to make it more powerful
I'd like to create a Module that dynamically binds instances to named annotations. The use case is I would like to automatically bind the values in my configuration with the key in the properties file being the #Named value.
However the configuration is bound in a different module so I need the config to be injected. Solutions I've looked at are:
Binding in the configure() method.
This method is not injected into and I can not get the base configuration.
Using a Provider/#Provides.
Providers only bind a single instance.
Using MultiBinder.
My use case is a little different then what is provided by this extension. Multi-binding allows you to bind multiple instances separately and then have them injected as a Collection more complex containing type. I would like to bind each instance separately and have them by uniquely identifiable for injection latter.
Use a childInjector.
Unfortunately this isn't possible without some extensive modification of existing code. This answer is a very good description of how to solve this problem this way though.
Inject the binder somehow. (I started getting a little hackier)
Guice allows injecting the Injector for latter use, I tried injecting the Binder into the Module though a #Provides method and then using the binder directly to make multiple binds within the method. Guice would not inject the binder.
Remember that all of the configure methods configure all of the bindings in an Injector before any injection can happen. That said, a few things:
Binding #Named properties to the contents of a single Properties instance is so useful, there's a Names.bindProperties(...) method that does it automatically for you. The only trick is that you need to have the Properties instance at the time configure() is run.
If they're all available at the same time, don't worry about binding the properties in one module and binding the application in another. As long as they all go into the same Injector, Guice will combine them all and let them satisfy each others' dependencies.
Providers can return different instances, and usually do--but you're right that it won't help you differentiate between keys. If injecting the Properties instance directly is too ugly, consider making a lightweight factory instead:
public class ConfigOracle {
#Inject private Properties properties;
public String getAsString(String key) { ... }
public int getAsInt(String key) { ... }
}
public class SomeConfigUser {
#Inject private ConfigOracle configOracle;
public void doStuff() {
doStuffBasedOn(configOracle.getAsString("my.properties.key"));
}
}
You should never need to inject a Binder (or anything else) into a Module.
If you implement Module, the binder will be a parameter of configure(). If you extend AbstractModule as you should, just call the binder() method.
You can pass in dependencies through constructor arguments to the Module, if need be, which (as far as I'm concerned) is the only way Modules should vary the bindings they create.
There's no reason you couldn't create a Module through an Injector, but you'd have to have an Injector first, and it sounds like you're trying to get away with only having one.
If you need other instances from the Injector you can always write a Provider implementation with #Inject fields/methods/constructors, or even take in parameters in a #Provides method (which will be filled in with dependencies automatically).
Overall I still favor the child injector approach (thanks for the link and compliment to my previous answer!), which fits your "dynamic bindings based on an injected instance" description the best, and would literally be this simple:
class PropertiesModule extends AbstractModule {
Properties properties;
PropertiesModule(Properties properties) {
this.properties = properties;
}
#Override public void configure() {
Names.bindProperties(binder(), properties);
}
}
Injector oldInjector = Guice.createInjector(allYourOtherModules);
Module myModule = new PropertiesModule(oldInjector.get(Properties.class));
Injector injector = oldInjector.createChildInjector(myModule);