hk2: why bind(X.class).to(X.class) - dependency-injection

I am learning Java, but found the following piece of code. I am confused. What is bind(X.class).to(X.class); for?
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class ApplicationBinder extends AbstractBinder {
#Override
protected void configure() {
bind(X.class).to(X.class);
}
}
Thanks

You're configuring how you want your services to be discovered in the DI (dependency injection) system. bind(Service).to(Contract) is basically saying that you want to provide the Service as an injectable service, and want to "advertise" it as Contract. By "advertise", I mean what you want to be able to inject it as. For instance Service can be UserRepositoryImpl, while Contract can be UserRepository (interface). With this you would only be able #Inject UserRepository as that's what you advertise. The benefit of this is all the benefits that come with programming to an interface.
Example
interface UserRepository {
List<User> findAll();
}
class UserRepositoryImpl implements UserRepository {
#Override
public List<User> findAll() {
return Arrays.asList(new User("username"));
}
}
#Path("users")
class UserResource {
#Inject
private UserRepository repository;
#GET
public List<User> getUsers() {
return repository.findAll();
}
}
class JerseyApp extends ResourceConfig {
public JerseyApp() {
register(UserResource.class);
register(new AbstractBinder() {
#Override
public void configure() {
bind(UserRepositoryImpl.class)
.to(UserRepository.class);
}
});
}
}
Here the UserRepository is injected into the UserResource. When the DI system injects it, it will actually be the UserRepositoryImpl instance.

By doing that you are actually binding a new contract to a service.
bind(Service.class).to(Contract.class);
OR (binding a new contract to a service in Singleton)
bind(Service.class).to(Contract.class)..in(Singleton.class);

Related

Play and Guice Dependency Injection with Interface

I'm trying to use Play/Guice dependency injection with an interface:
public interface IService {
Result handleRequest();
}
public Service implements IService {
#Override
public Result handleRequest() {
...
return result;
}
}
public class Controller {
private final IService service;
#Inject
public Controller(IService service) {
this.service = service;
}
}
I get:
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1.) No implementation for IService was bound.
If I change the controller class to not use the interface it works fine:
public class Controller {
private final Service service;
#Inject
public Controller(Service service) {
this.service = service;
}
}
How do I make it work with the interface so it finds the concrete Service class?
You can use guice annotation #ImplementedBy like this:
import com.google.inject.ImplementedBy;
#ImplementedBy(Service.class)
public interface IService {
Result handleRequest();
}
Or u can use modules like this:
import com.google.inject.AbstractModule;
public class ServiceModule extends AbstractModule {
protected void configure() {
bind(IService.class).to(Service.class);
}
}
And then register them in application.conf play.modules.enabled += "modules.ServiceModule"

Inject dependencies into ServletContextListener using HK2 in Jersey

In order to initialize the application at startup, I extended ServletContextListener:
#WebListener
public class MyServletContextListener implements javax.servlet.ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
... initialization code here
}
#Override
public void contextDestroyed(ServletContextEvent sce) {}
}
Now I want to extract the initialization logic into a standalone StartupManager class, and delegate to this class from MyServletContextListener:
public class StartupManager {
public void performStartup() {
... initialization code here
}
}
I tried to inject StartupManager into ServletContextListener by simply adding #Inject annotation:
#WebListener
public class MyServletContextListener implements javax.servlet.ServletContextListener {
#Inject StartupManager mStartupManager;
#Override
public void contextInitialized(ServletContextEvent sce) {
mStartupManager.performStartup();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {}
}
This did not work - the reference is null when contextInitialized(ServletContextEvent ) is called.
Then I thought that I might have to register a binder:
#ApplicationPath("")
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new DependencyInjectionBinder());
}
}
public class DependencyInjectionBinder extends AbstractBinder {
#Override
protected void configure() {
bind(StartupManager.class).to(StartupManager.class);
}
}
This did not work either.
My question is how can I perform injection of dependencies into ServletContextListener? Preferably constructor injection, but field injection will also be alright.
It's not going to work, as the servlet listener and Jersey are not linked to the same system. As an alternative, you can use Jersey's Event Listeners. You can implement an ApplicationEventListener where you would be able to initialization and clean up in the same way you would in the servlet listener. You would be able to inject your services into Jersey's listener.

Jersey injection

Is there a way to change the implementation of UriInfo that's injected into all the resources and classes? I want to keep most of the implementation the same, but just change one part of it (the part that provides a UriBuilder - I want to provide a different implementation of the UriBuilder).
You can create wrapper around the original UriInfo
public class MyUriInfo implements UriInfo {
private final UriInfo delegate;
public MyUriInfo(UriInfo uriInfo) {
this.delegate = uriInfo;
}
#Override
public String getPath() {
return delegate.getPath();
}
#Override
public UriBuilder getRequestUriBuilder() {
return new MyUriBuilder();
}
...
}
Then just create a Factory to return your custom UriInfo. This Factory will be used by the DI framework to inject the UriInfo.
public class MyUriInfoFactory
extends AbstractContainerRequestValueFactory<MyUriInfo> {
#Override
public MyUriInfo provide() {
return new MyUriInfo(getContainerRequest().getUriInfo());
}
}
Then just create the AbstractBinder and register it with the ResourceConfig
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bindFactory(MyUriInfoFactory.class)
.to(UriInfo.class)
.in(RequestScoped.class)
.proxy(true)
.proxyForSameScope(false)
.ranked(10);
}
}
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new Binder());
}
}
If you are using web.xml, check out this post.
Now you should be able to just inject it
#GET
public String get(#Context UriInfo uriInfo) {
return uriInfo.getClass().getName();
}
If you want to be able to retain being able to inject the original UriInfo, you can change the binding to
bindFactory(MyUriInfoFactory.class)
.to(MyUriInfo.class) // <--- Change here to MyUriInfo
.in(RequestScoped.class)
.proxy(true)
.proxyForSameScope(false)
.ranked(10);
This way, you would need to inject MyUriInfo
#GET
public String get(#Context MyUriInfo uriInfo) {
return uriInfo.getClass().getName();
}
Doing this, you are still able to inject the original UriInfo if you needed to.
See Also:
Custom Injection and Lifecycle Management

multiple ejb injections which implement the same interface

i am very new to this ejb stuff. is there any possibility that in a single file i can have multiple injections based on some criteria.
for eg
public interface common(){
public void sayhello();
}
beanA
implements common()
beanB
implements common()
both are stateless beans
now i have a client which needs to trigger hello method based on some criteria. for eg. say based on console input if string contains A then beanA should be injected otherwise beanB.
Is there any possibility? and again my next question is , can i say this dynamic injection is not managed by container? if so how can i let container take the control? i need a sample code or atleast any tutorial ref.
thanks in advance!!
No, this is not really possible. You might be able to get close with a custom CDI scope that uses a thread local or session attribute, but I wouldn't recommend it. Instead, just inject a reference to both EJBs, and select the one to use as needed:
#EJB(beanName="BeanA")
Common beanA;
#EJB(beanName="BeanB")
Common beanB;
private Common getCommon(String input) {
return isBeanAInput(input) ? beanA : beanB;
}
you could do something like this:
public interfaces ICommon {
public void sayhello();
}
#Stateless
#LocalHome
public class BeanA implements ICommon {
public void sayhello() {
// say hallo
}
}
#Stateless
#LocalHome
public class BeanB implements ICommon {
public void sayhello() {
// say hallo
}
}
and here the CDI "client" which uses the EJB services
#Model
public void MyJSFControllerBean {
#Inject
private BeanA beanA;
#Inject
private BeanB beanB;
public String sayhello(final String input) {
if("a".equals(input)) {
beanA.sayhello();
} else {
beanB.sayhello();
}
return "success";
}
}
Or the other solution would be that you create a CDI producer to create this. but then you are mixing two different concepts. but i think it depends ou your concrete usecase.
dynamic injection does not exist! with #Produce and #Qualifier you can control the creation of the required CDI beans to inject. but this is only for CDI not for EJB.
here the CDI producer example:
public void ICommonProducer {
#EJB
private BeanA beanA;
#EJB
private BeanB beanB;
#Produces
public ICommon produce() {
final String input = "?????";
// but here you have the problem that must get the input from elsewhere....
if("a".equals(input)) {
beanA.sayhello();
} else {
beanB.sayhello();
}
}
}
#Model
public void MyJSFControllerBean {
#Inject
private ICommon common;
public String sayhello(final String input) {
common.sayhello();
return "success";
}
}
i have not teseted this code...

How Google Guice is working without #Inject anywhere in my test program?

I started exploring Google Guice today to do dependency injection in my application.
I noticed I am not using #Inject annotation anywhere. But it's working. Can not understand this concept. In this example, where #Inject is the best fit in my scenerio? If any one can point me out.
public interface Tweeter {
public void sendTweet(String message);
}
public class SmsTweeter implements Tweeter {
#Override
public void sendTweet(String message) {
System.out.println("You SMS tweet: "+message);
}
}
import com.google.inject.AbstractModule;
public class TweetModule extends AbstractModule{
#Override
protected void configure() {
bind(Tweeter.class).to(SmsTweeter.class);
}
}
import com.google.inject.Guice;
import com.google.inject.Injector;
public class TestTweetClient {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new TweetModule());
Tweeter tweeter = injector.getInstance(Tweeter.class);
tweeter.sendTweet("Hi there");
}
}
It prints (the hidden implementation works):
You SMS tweet: Hi there
There is no best fit for #Inject in your example. The class SmsTweeter has an implicit zero-args constructor. You could make it explicit and add #Inject there but it is not necessary.
public class SmsTweeter implements Tweeter {
#Inject
SmsTweeter() {
// nothing to do
}
#Override
public void sendTweet(String message) {
System.out.println("You SMS tweet: "+message);
}
}

Resources