public class Servlet2Stateless extends HttpServlet {
#EJB private HelloUserLocal helloUser;
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
out.println(newSess.getName());
}
will above line of code work when I have EJB and Servlet deployed on different servers? or I need to call it through traditional way????
If the EJB resides on the different server than your client (Servlet) than you cannot use the dependency injection with #EJB annotation.
I guess that you'll need to go with the old JNDI way.
According to EJB 3.1 spec, you can use #EJB annotation in a variety of clients, including servlets which is your case.
The problem is that you are running client and server in different hosts. Depending on the server you are using, you might be able to use the EJB annotation. This post explains how to do it in Weblogic.
Needless to say you have to define the server EJB as #Remote in either case.
If your container also supports CDI, you could write a CDI producer method for the bean whcih does the JNDI lookup. Then you can at least separate the lookup from the injection site.
What about using dependency injection in a standalone client ?
Related
Using DropWizard(Jersey Server), Is it possible to access HttpServletRequest from an Authenticator?
I would give it an attribute.
I tried with:
#Context
private HttpServletRequest servletRequest;
But it's not injected.
I registered my Authenticator using:
env.jersey().register(
new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>().setAuthenticator(new FooAuthentificator())
.setRealm("Realm").buildAuthFilter()));
It's possible, but the problem is, the Authenticator never goes through the DI lifecycle, so it never gets a chance to get injected. What we can do though is explicitly inject it ourselves. To do that, we need to get a hold of the ServiceLocator (which is the main IoC container, kind of like ApplicationContext with Spring). Once we have the ServiceLocator, we can call locator.inject(anyObject) to explicitly resolve any injection dependencies.
The easiest place to get the ServiceLocator, when configuring the app, is in a Feature. Here we can also register Jersey components. Calling register on the FeatureContext (seen below) is just like calling env.jersey().register(...) with Dropwizard, it has the same effect. So we can do
public class AuthenticatorFeature implements Feature {
#Override
public boolean configure(FeatureContext ctx) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(ctx);
TestAuthenticator authenticator = new TestAuthenticator();
locator.inject(authenticator);
ctx.register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(authenticator)
.setRealm("SEC REALM")
.buildAuthFilter()));
ctx.register(new AuthValueFactoryProvider.Binder<>(User.class));
return true;
}
}
You can see that explicitly inject the authenticator, with the call to locator.inject(authenticator). Then we register this feature through Dropwizard
env.jersey().register(new AuthenticatorFeature());
Tested, and works fine.
Note, if you are wondering how it's possible to inject the HttpServletRequest, when there is no current request, it's because a proxy is injected. Same thing as if you were to inject the request into a Jersey filter, the same thing happens; a proxy is injected, as there is only a singleton filter, but the request changes from request to request, so a proxy needs to be injected.
See Also:
Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey
I am new to this so I appreciate the help. I am using Castle Windsor as my container with XML config. For several of my core services this works perfectly, I simply declare a public property named the same thing and it injects it as expected. Most of my core services have no-arg constructors, those ones work out of the box. But what about if I have a core service that itself has it's own dependencies, how best to deal with that? For example, say I have a configurable message queuing service:
public interface IQueueService {
void SendMessage(string msg);
}
public class SQSService : IQueueService {
private ServiceConfig _config;
public SQSService(ServiceConfig config) {
_config = config;
}
public void SendMessage(string msg){
//do message stuff
}
}
SQSService itself requires a config to initialize properly (endpoint, port, etc). Is there an easy way to configure the DI to resolve this config? Or am I better off re-factoring the SQSService to not have this dependency?
When injecting something that is dependent on a config, session, request, etc., you have the flexibility to break away from making your dependency object have the same structure as the underlying source (in fact, you should as much as possible, otherwise you may end up accidentally writing code that implicitly depends on that structure). Inject the properties you need, rather than the config itself. I am not sure how to accomplish this using the XML config, but I know the fluent API allows for injection using .FromAppSettings(), or you can use the web/app.config to house your config, using .FromAppConfig() as explained here:
How to instantiate a class based on web.config file with Castle Windsor?
I am not sure whether I understood the exact way of how these two does the injection using #Inject,but I recently developed an app where during the first phase of development I used Dependency Injection using #inject of HK2 and binded the resources using abstract binder,it worked fine.Then I wanted to inject one more value. I needed to inject a basic String values using #Inject and the value for this was got form a method annotated with #Produces.But when I do that I get this error.
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String
I read in many places and many suggest CDI and HK2 have some issues working together.I am not able to resolve the issue.
When I try the above scenario in two different standalone programs they run fine.But when I integrate them I get the above error message.
This is what I found in java's jira:
https://java.net/jira/browse/GLASSFISH-20597
My example is:
public ClassA{
#Inject
ClassBInter b;
}
I binded the class b in the abstract binder
new AbstractBinder(){
#Override
protected void configure() {
//Binding the implementation to the interface
bind(ClassBImpl.class).to(ClassBInter.class);
}
}
this worked fine.
but when I tried the below concept of adding an #Inject to a String in the same system,it crashes with the above exception
public ClassC{
#Inject
String name;
}
Producer Class
public ProducerClass{
#Produces
public String getName(){
return "henry Ford";
}
}
String injection is generally not supported, across the board. You can use qualifiers, which should help with resolution.
Do you have a beans.xml file in your deployment?
I have a web project that has FacesValidator, this validator needs to access an EJB service to verify if a record exists. Unfortunately, I cannot inject my enterprise beans since the validator is not a managed-bean, so I'm trying to access it via InitialContext. I've tried different combination from http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html but failed.
What works is this format:
java:global/myProject-ear-1.0.0/myProject/MyService!com.czetsuya.myProject.service.membership.MyService,
My question is can it be simplify? Seems too long.
Thanks,
czetsuya
Look at the server logs. A bit decent EJB container (at least, Glassfish 3 and JBoss 6/7 do), logs all available JNDI names of the EJB during EJB deployment step. Provided that the validator is properly been put in the WAR and the EJB has a #Local interface, then the shortest JNDI name would be the java:app one which should in your case have been java:app/myProject/MyService.
A completely different alternative is to just make the validator a JSF or CDI managed bean instead, so that you can just use the #EJB annotation.
#ManagedBean // Or #Named.
#ApplicationScoped // Provided that the instance doesn't have any state.
public class MyValidator implements Validator {
#EJB
private MyService myService;
// ...
}
and reference it by binding instead of validatorId:
<f:validator binding="#{myValidator}" />
Note that from JSF 2.2 on, you should be able to inject #EJB in a #FacesValidator (and #FacesConverter).
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired
Folks,
I am very annoyed by having to re-learn and waste time with this stuff every time a new version of JBoss rolls around.
I have a stateless EJB that is discovered and declared in the JNDI space:
10:01:53,044 INFO [org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
DTalk/UserManager/local - EJB3.x Default Local Business Interface
DTalk/UserManager/local-com.doctalk.ejb.UserManagerLocal - EJB3.x Local Business Interface
I need to use this EJB in a servlet which is part of a war which is part of the EAR that contains the EJB. I'd like to do it using injection.
When I use the most intuitive notation:
#EJB
private UserManager userManager;
I get an exception in JBoss logs.
When I use a more flowery notation such as:
#EJB( mappedName = "UserManager" )
private UserManager userManager;
Or
#EJB( mappedName = "DTalk/UserManager/local" ) // EAR is called DTalk
private UserManager userManager;
I get no injections errors in jboss but the injected bean is null.
This is maddening and a huge waste of time and makes me question why I don't dump the Eclipse/jboss tools franchise in favor of NetBeans and GlsssFish.
Any insights appreciated.
Thanks.
You are trying to inject (a proxy to) the bean instance itself, instead of its interface.
Yet, according to the deployment logging you've shown, you have only declared the bean to be bounded in JNDI via its (local) interface. In order to make the injection happen, you should either declare the variable in which you're injecting as the interface:
#EJB
private UserManagerLocal userManager;
OR declare that a no-interface view should be created for your bean:
#Stateless
#LocalBean
public class UserManager implements UserManagerLocal {
...
}
after which you can declare the variable as you did earlier:
#EJB
private UserManager userManager;