Injecting a remote EJB in a managedBean - jsf

I'm stuck since x time on how to inject a remote EJB in a managed bean of a JSF application.
I've created a simpl java application and i've come to inject the remote EJB with the lookup... and it works.
but when i come to the web application i really don't know what to do !!!
here is my EJB code:
#Stateless
public class Hello implements HelloRemote {
#Override
public String sayHello(String name) {
return "Hello, "+name;
}
}
the Remote interface is
#Remote
public interface HelloRemote {
public String sayHello(String name);
}
in my web application i vre created i managed bean :
#ManagedBean
public class MyBean {
#EJB
HelloRemote helloRemote;
}
BUT IT DOESN'T WORK :(

If you want to expose EJB locally you have to use #Local on Interface.
If you want to expose both locally and remotely you have to created 2 Interfaces, one with #Local and one with #Remote.
If your JSF ManagedBean(MyBean) is running locally ie.,Running on same App server as EJB you can directly inject it using #EJB.
If your JSF ManagedBean is running on different server, you have to use the JNDI Registry to look up and access the EJB.

Related

How to inject RequestScoped bean into Axis2 POJO web service?

We are currently building a web application where the backend is exposing the server functionality via REST web services (using Jersey). However, there is one web service which needs to be a SOAP service due to backwards compatibility. We have for this implemented a POJO (generated as Axis2 web service using Eclipse to get the setup right) which we deploy as an Axis2 web service on a Tomcat. The SOAP web service is defined as request scoped (done in services.xml). Calling this web service, using both Kerberos and NTLM for authentication (which one depends on the environment where the web app is deployed) works fine.
Now, we want to reuse some of the functionality of the REST services. The REST services are only used as facades and the business logic are implemented in #RequestScoped beans being injected into the REST services using CDI and #Inject. It would be perfect if we could inject a #RequestScoped bean into our POJO but this doesn't seem to work. The bean to be injected also have dependencies on other #RequestScoped beans which are also injected using CDI. Basically, it will cause an entire tree of object dependencies to be instanciated.
Now, my question is if this scenario should in general be possible, i.e. injecting a #RequestScoped bean into an Axis2 POJO using CDI? If not, do you have any suggestions of how this could be solved in a different manner, i.e. reusing #RequestScoped beans in an Axis2 POJO?
Here are some code samples of our setup:
POJO:
import javax.inject.Inject;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.transport.http.HTTPConstants;
public class MyService {
#Inject
private MyRequestScopedService mrss;
public MyResponse getSomeData(MyRequest myRequest) {
// some logic...
}
}
Bean to inject:
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
#RequestScoped
public class MyRequestScopedService {
#Inject
private MyOtherRequestScopedService morss;
[...] // a few other beans are also injected
public SomeData getSomeData(SomeRequest someRequest) {
// some logic...
}
[...]
}
services.xml
<service name="MyService" scope="request">
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<parameter name="ServiceClass" locked="false">com.domain.MyService</parameter>
</service>
If you need some more details, please let me know.

Inject an application scoped managed bean in a websocket

I'm developing a real time application. I have websockets and application scoped managed bean. I'm trying to access the application scoped managed bean from a websocket but I can't. Is this possible?
This is my websocket and managed bean (application scoped):
#ServerEndpoint("/mediador")
#ManagedBean(eager = true)
#ApplicationScoped
public class Mediador implements Serializable {
#ManagedProperty(value = "#{aplicacion}")
private Aplicacion aplicacion;
...
And my "Aplicacion" managed bean:
#ManagedBean(eager = true)
#ApplicationScoped
public class Aplicacion implements Serializable {
...
If I try to access in Mediador class to de managed property "aplicacion" it's null so I get a NullPointerException.
Thanks
This is really not right.
#ServerEndpoint("/mediador")
#ManagedBean(eager = true)
#ApplicationScoped
public class Mediador implements Serializable {
WS (JSR-356 WebSocket) API and JSF API are completely independent from each other. They know nothing from each other and won't take mixed annotations from each other into account.
Effectively, you end up with two instances of the class. One as a WS managed server endpoint as available by ws://.../mediador, and one as a JSF managed bean as available by #{mediador}. The #ManagedProperty is only recognized by JSF managed bean facility and it'll work in the JSF managed bean instance only.
Use CDI instead. It works across the entire Java EE web application. Not only in WebSocket endpoints, but also in JSF managed beans, WebServlets, WebFilters, WebListeners, JAX-RS resources, JAX-WS resources, etcetera. Eventually, JSF managed bean facility will be deprecated in favor of CDI. This will happen in Java EE 9 or perhaps already 8.
#ServerEndpoint("/mediador")
public class Mediador { // Shouldn't be serializable!
#Inject
private Aplicacion aplicacion;
// ... (no getter+setter needed!)
}
#Named
#ApplicationScoped // javax.enterprise.context
public class Aplicacion { // Shouldn't be serializable!
// ...
}
Unrelated to the concrete problem: implementing websockets in JSF rightly is not exactly trivial, certainly not if you'd like to take into account JSF session and view scopes, and would like to be able to target a specific user during push. You'd better look at an existing push component. See also How can server push asynchronous changes to a HTML page created by JSF?

Inject EJB bean from JSF managed bean programmatically

I have EJB stateless bean.
How can I inject it to JSF managed bean by programmatic instead of #EJB annotation?
You can't inject it programmatically. You can however obtain it programmatically. EJBs are also available via JNDI. Usually, you find those JNDI names/aliases printed in server startup log. At least JBoss / WildFly does that.
There are different JNDI name aliases:
java:global/APP_NAME[/MODULE_NAME]/EJB_NAME
java:app/MODULE_NAME/EJB_NAME
java:module/EJB_NAME
Where /APP_NAME is the name of the WAR or EAR application, and /MODULE_NAME is the name of the EJB module in case of an EAR application, or the WAR module in case of a single-WAR application (and this will be absent in java:global as it otherwise repeats /APP_NAME), and /EJB_NAME defaults to the class name of the EJB class.
The java:global is accessible through the entire server. The java:app is only accessible from inside the same application (WAR or EAR). The java:module is only accessible from inside the same module (EJB in case of EAR or WAR itself in case of single-WAR).
A JSF managed bean is obviously inside a WAR. If you've a single-WAR application, then java:module/EJB_NAME must work. If you've however an EAR project, then the EJB is obviously inside the EJB module, in that case the java:module won't work and you'd need java:app or java:global.
So, given an EJB like below,
#Stateless
public class FooService {}
it's in a single-WAR project named "foo_war" via JNDI available in a JSF managed bean as follows (usually you do that in #PostConstruct method):
InitialContext jndi = new InitialContext();
FooService fooService = (FooService) jndi.lookup("java:module/FooService");
// Or
FooService fooService = (FooService) jndi.lookup("java:app/foo_war/FooService");
// Or
FooService fooService = (FooService) jndi.lookup("java:global/foo_war/FooService");
or in an EAR project named "foo_ear" with an EJB module named "foo_ejb" with therein the EJB class (while the JSF managed bean is in the WAR module of the EAR project):
InitialContext jndi = new InitialContext();
FooService fooService = (FooService) jndi.lookup("java:app/foo_ejb/FooService");
// Or
FooService fooService = (FooService) jndi.lookup("java:global/foo_ear/foo_ejb/FooService");

How do I force an application-scoped bean to instantiate at application startup?

I can't seem to find a way to force an application-scoped managed bean to be instantiated/initialized when the web app is started. It seems that application-scoped beans get lazy-instantiated the first time the bean is accessed, not when the web app is started up. For my web app this happens when the first user opens a page in the web app for the first time.
The reason I want to avoid this is because a number of time-consuming database operations happen during the initialization of my application-scoped bean. It has to retrieve a bunch of data from persistent storage and then cache some of it that will be frequently displayed to the user in the form of ListItem elements, etc. I don't want all that to happen when the first user connects and thus cause a long delay.
My first thought was to use an old style ServletContextListener contextInitialized() method and from there use an ELResolver to manually request the instance of my managed bean (thus forcing the initialization to happen). Unfortunately, I can't use an ELResolver to trigger the initialization at this stage because the ELResolver needs a FacesContext and the FacesContext only exists during the lifespan of a request.
Does anyone know of an alternate way to accomplish this?
I am using MyFaces 1.2 as the JSF implementation and cannot upgrade to 2.x at this time.
My first thought was to use an old style ServletContextListener contextInitialized() method and from there use an ELResolver to manually request the instance of my managed bean (thus forcing the initialization to happen). Unfortunately, I can't use an ELResolver to trigger the initialization at this stage because the ELResolver needs a FacesContext and the FacesContext only exists during the lifespan of a request.
It doesn't need to be that complicated. Just instantiate the bean and put it in the application scope with the same managed bean name as key. JSF will just reuse the bean when already present in the scope. With JSF on top of Servlet API, the ServletContext represents the application scope (as HttpSession represents the session scope and HttpServletRequest represents the request scope, each with setAttribute() and getAttribute() methods).
This should do,
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("bean", new Bean());
}
where "bean" should be the same as the <managed-bean-name> of the application scoped bean in faces-config.xml.
Just for the record, on JSF 2.x all you need to do is to add eager=true to #ManagedBean on an #ApplicationScoped bean.
#ManagedBean(eager=true)
#ApplicationScoped
public class Bean {
// ...
}
It will then be auto-instantiated at application startup.
Or, when you're managing backing beans by CDI #Named, then grab OmniFaces #Eager:
#Named
#Eager
#ApplicationScoped
public class Bean {
// ...
}
Romain Manni-Bucau posted a neat solution to this that uses CDI 1.1 on his blog.
The trick is to let the bean observe the initialization of the built-in lifecycle scopes, i.e. ApplicationScoped in this case. This can also be used for shutdown cleanup. So an example looks like this:
#ApplicationScoped
public class ApplicationScopedStartupInitializedBean {
public void init( #Observes #Initialized( ApplicationScoped.class ) Object init ) {
// perform some initialization logic
}
public void destroy( #Observes #Destroyed( ApplicationScoped.class ) Object init ) {
// perform some shutdown logic
}
}
As far as I know, you can't force a managed bean to be instantiated at application startup.
Maybe you could use a ServletContextListener which, instead of instantiating your managed bean, will perform all the database operations itself?
Another solution might be to instantiate your bean manually at application startup, and then set the bean as an attribute of your ServletContext.
Here is a code sample:
public class MyServletListener extends ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
MyManagedBean myBean = new MyManagedBean();
ctx.setAttribute("myManagedBean", myManagedBean);
}
}
In my opinion, this is far from clean code, but it seems like it does the trick.
Additionally to BalusC's answer above you could use #Startup and #Singleton (CDI), e.g.
//#Named // javax.inject.Named: only needed for UI publishing
//#Eager // org.omnifaces.cdi.Eager: seems non-standard like taken #Startup below
#Startup // javax.ejb.Startup: like Eager, but more standard
#Singleton // javax.ejb.Singleton: maybe not needed if Startup is there
//#Singleton( name = "myBean" ) // useful for providing it with a defined name
#ApplicationScoped
public class Bean {
// ...
}
which is nicely explained here.
Works in JPA 2.1 at least.

Seam - EJB3 in Web Module/WAR?

I'm writing an application using Seam 2.2.x which will be deployed on JBoss 5.1. I have an EJB module with all of the business logic en EJB's. However, I'd also like to have statless session EJBs in the web module to act as action classes. Is this possible? Do I need to perform any additional configuration to get this working? I have an interface I've defined:
#Local
public interface ContentItemSearchAction extends Serializable {
...
}
...and an implementing class...
#Name("contentItemSearchAction")
#AutoCreate
#Stateless
public class ContentItemSearchActionBean implements ContentItemSearchAction {
...
}
However, when I try to access the EJB in one of my JSF views, I get the following exception:
Caused by javax.naming.NameNotFoundException with message: "ContentItemSearchActionBean not bound"
Has anyone seen this before? What am I missing? Why is the EJB in my WAR module not being picked up?
EJBs do not go into WAR files. They're packaged into JARs, which go into the EAR along with the WAR.
The EJBs need not be in the WAR to be visible from your web tier.

Resources