Access JSF2 Managed Bean from RESTful Web Service - java

I have an application scoped managed bean which contains a list read from the database. Whenever another application makes changes to the database, it should trigger the web service to update the list in the managed bean.
I've tried
FacesContext context = FacesContext.getCurrentInstance();
ApplicationBean application= (ApplicationBean) context.getApplication().evaluateExpressionGet(context, "#{applicationBean}", ApplicationBean.class);
The context variable was null, probably because the web service isn't called in the JSF context.
The REST resource class looks something like this:
#Path("/application")
public class ApplicationResource {
#PUT
#Path("{id}")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.TEXT_PLAIN)
public void updateIdCache(#PathParam("id") String internalid) {
ApplicationBean application = ???;
application.update(id);
return;
}
}
The application server in use is tomcat 6. How is it done correctly?
Thanks & best regards

Don't think what you want is possible with JSF managed beans.
CDI beans have this functionality though.
JAX-WS with CDI:
http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0
CDI implementation weld is commonly used:
Getting started with weld (covers tomcat 6)
http://docs.jboss.org/weld/reference/1.0.0/en-US/html/gettingstarted.html
btw I love to work with CDI and I only use tomcat 6/7

Related

Referencing EJB Local home from a POJO class of a separate web application

I am trying to port 2 EJB modules in my application from EJB2.1 to EJB3.0. I am using the Eclipse Kepler IDE and regenerated the session beans using an EJB3.0 configuration. I am not using an ejb-jar.xml because in EJB 3.0 that is supposed to be redundant. I have instead used annotations for marking my bean as Stateless and specifying the Local and Local Home Interfaces. I have still kept the Local Home interface since I wanted the basic structure of my project to be similar to what it was in EJB2.1. I have also done away with the xml bindings for the EJB while migrating.
We are using a WAS 7 application server for deployment and while the EJB is getting successfully deployed without errors, I am getting a naming Exception while looking up my Local Home interface from a separate POJO class of a different web application it is required in. I basically want to call the create() method of the Local Home interface after referencing the EJB Local Home. Adding code samples below:
Session Bean:
#Stateless
#Local(AccessLDAPSessionLocal.class)
#LocalHome(AccessLDAPSessionLocalHome.class)
public class AccessLDAPSessionBean implements AccessLDAPSessionLocal {
//Business Logic
}
Local Interface:
public interface AccessLDAPSessionLocal {
//business Interface
}
Local Home Interface:
public interface AccessLDAPSessionLocalHome extends EJBLocalHome {
public AccessLDAPSessionLocal create() throws CreateException;
}
Pojo class referencing the Local Home interface:
public static AccessLDAPSessionLocal getAccessLDAPSessionBean() throws NamingException, CreateException {
if (accessLDAPSessionBean == null) {
InitialContext context = new InitialContext();
Object obj = context.lookup("java:global/AccessLDAP/AccessLDAPSessionBean!com.ibm.asset.hrportal.core.ejb.ldap.AccessLDAPSessionLocalHome");
accessLDAPSessionBean = ((AccessLDAPSessionLocalHome) obj).create();
}
return accessLDAPSessionBean;
}
Also my Local and Local Home interfaces are inside my EJB client which I use as a jar file, while my Session Bean is inside the actual EJB which is used as an EAR.
Following is the error I am getting:
NamingException::javax.naming.NameNotFoundException: Name global not found in context "java:".
Am I missing some configuration resulting in the failure of JNDI lookup? Any help would be gratefully appreciated. Thanks in advance.
WebSphere Application Server 7.0 is only an implementation of EJB 3.0, but the java:global namespace wasn't added until EJB 3.1, which wasn't implemented in WebSphere Application Server until 8.0. As with all EJB 3.0 implementations, you will need to lookup a vendor-specific binding name. You can find the WebSphere Application Server binding name by looking at the CNTR0167I messages in SystemOut.log. See the EJB 3.0 application bindings overview topic in the Knowledge Center if you would like to customize this binding name.
Regardless, it is not a best practice to directly lookup EJBs by their binding name. Instead, you should use an EJB reference. In EJB 3.0, that means using an annotation like this in an EE managed object (such as a servlet or another EJB):
#EJB
private AccessLDAPSessionLocalHome home;
In this case, the EJB container is required to find a target EJB within the same application that contains the EJB reference, so you do not need to explicitly configure a target binding name for the EJB reference.
If you need to access the EJB reference from a utility class rather than an EE managed class, then declare the EJB reference with a name on a managed class (such as a servlet or another EJB), and look it up from the utility class:
#EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class)
public class MyServlet { ... }
public class MyUtility {
...
InitialContext context = new InitialContext();
Object obj = context.lookup("java:comp/env/ejb/accessHome");
...
}
You can configure multiple such EJB references on the same managed EE class using the #EJBs annotation:
#EJBs({
#EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class),
#EJB(name = "ejb/other" beanInterface = Other.class)
})
public class MyServlet { ... }
If your EJB is packaged in a separate EAR, then note that this is not a portable configuration. See the "Local client views" section of the EJB modules topic in the Knowledge Center. Additionally, you will need to explicitly configure a binding name for the EJB reference.
I think the way you are looking up the ejb is not correct. The JNDI name would be something like "java:comp/env/". ejb-ref-name would be part of your web.xml
Also, you will need to give providerURL and factoryName to the context object before doing the lookup.

Inject a singleton in an ExceptionMapper

I have an ExceptionMapper defined as following
#Provider
public class MyExceptionMapper implements ExceptionMapper<Throwable> {
#Inject
private Manager myManager;
#Override
public Response toResponse(Throwable exception) {
// My implementation
}
}
Deploying this code on glassfish 4 results with exception:
org.glassfish.hk2.api.UnsatisfiedDependencyException:
There was no object available for injection at
Injectee(requiredType=Manager,parent=MyExceptionMapper,qualifiers {}),position=-1,optional=false,self=false,unqualified=null,955636053)
When I use #Context instead of #Inject I do not see the exception but myManager is null
I tried making MyManager as #ManagedBean, #Singleton or an EJB (Stateless, Singleton) and non works
In JEE6 (with glassfish 3) you have to add
#javax.annotation.ManagedBean
to the provider implementation. Possibly this works also for Glassfish 4
As far as I know, this issues comes from the following. CDI is not in place to manage the dependencies of restful services and providers by default. But when adding #ManagedBean you enable CDI to create the instance.
Here is an example where I introduced CDI to a restful service using jersey.
You can follow the updates regarding this issue here https://java.net/jira/browse/JERSEY-2393
You could use OmniFaces Beans to get a CDI managed bean instance in your ExceptionMapper:
Beans.getInstance(Bean.class)
I'm using this with #javax.ejb.Stateless beans containing #javax.persistence.PersistenceContext.

Web Service Client in a Stateless Enterprise Bean

What is the correct way to implement a stateless EJB 3.1 for invoking a web service. My client works as a Servlet, but I want to move the invocation into a EEJ bean. I have to add username and password in the SOAP header envelop to access the WS, which is working fine.
The service the the servlet is using looks like this;
#WebServiceClient(name = "MessageService", targetNamespace = "http://...", wsdlLocation = "...wsdl")
public class MessageService
extends Service
Can I wrap MessageService in a Stateless EJB or should the bean itself use #WebServiceRef (as in the tutorial) without wrapping the MessageService ?
Tutorial
Local Service
If the client and the provider lives in same EAR or WAR on the application server, can be invoked like a ordinal EJB. e.g.
#WebService
#Stateless
public class CalculatorBean implements Calculator {
public int add(int a, int b) {
return a + b;
}
}
The CalculatorBean is threadsafe. All business logic that occurs within the add method
is part of a container-managed transaction and not participate in any global transaction.
Alternatively, the client code can look up in the JNDI namespace.
Remote Service
The runtime can inject a service object or a port object into a member variable annotated with javax.xml.ws.WebServiceRef.
#WebServiceRef(CalculatorService.class)
private Calculator port;
The CalculatorService class is annotated with the javax.xml.ws.WebServiceClient annotation (the client of the service), which has a wsdlLocation attribute.
If you want to wrap the WebService into the EJB, see this answer. For read a discussion about this, see EJB and Web Services: getting the best of both worlds.

Possible to inject #ManagedBean as a #ManagedProperty into #WebServlet?

In my Java EE 6-webapp (running on latest GlassFish 3.1), I'm using JSF2-ManagedBeans and #ManagedProperty to inject them into other ManagedBeans. Now i would like to know if i can also inject a #ManagedBean into a #WebServlet, using #ManagedProperty. Some code:
#WebServlet(name = "vdd")
public class VddServlet extends HttpServlet
{
#ManagedProperty(value = "#{userIdentity}")
private UserIdentity identity;
}
The ManagedBean looks like this:
#ManagedBean
public class UserIdentity
{
...
}
Does it work like this? If not, what other ways do i have to inject a ManagedBean into a WebServlet (without CDI, which is currently not an option - since there are some issues in GF 3.1 B32/33 in combination with OSGi-Java EE-apps, but we are short on time)?
Using #ManagedProperty in a servlet is not possible since this works in #ManagedBean classes only. Further, injecting an object which has a lesser scope than the parent itself is also not possible since that would also only end up in concurrency problems. The injector would throw a runtimeexception for that. A servlet is in essence application scoped and shared among all users and your UserIdentity bean seems to be session scoped.
Since JSF runs on top of the Servlet API and stores the session scoped beans in, well, the session, you could in the servlet just grab it as session attribute:
UserIdentity identity = (UserIdentity) request.getSession().getAttribute("userIdentity");
Note that the FacesContext is usually also not available in a servlet other than FacesServlet, so using FacesContext in the servlet as suggested in a comment does not make any sense, that would only return null.

Get reference to spring bean from #WebService

I'm using CXF to generate a web service from wsdl.
The generated web service has the annotation #WebService
How do i get a reference to spring bean from the web service?
All my spring beans are annotated with #Service, and I can access them
in my web application. How do I access them also from my web service?
I've tried the following:
public class TestWSImpl implements TestWSSoap{
#Resource
public WebServiceContext wsContext;
#Override
public String getTest() {
ServletContext servletContext= (ServletContext) wsContext.getMessageContext().get(MessageContext.SERVLET_CONTEXT);
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
return "Test";
}
}
But the getWebApplicationContext method returns null
When I replace getWebApplicationContext with getRequiredWebApplicationContext
I get an error message: No WebApplicationContext found: no ContextLoaderListener registered?
Anyone has an idea?
Thanks
Alon
If you were using JUnit 4.4 or higher you could inject it using the Spring 2.5 JUnit annotations. Here's an example.
http://hamletdarcy.blogspot.com/2008/12/autowired-junit-tests-with-spring-25.html
Of course it goes without saying that this approach requires that the web service be running in a web context when the test is started. Have you done that?
You also might prefer testing WSDL based services using SOAP UI.
It was a long time ago.
I'm looking on my code and I see that I put the following method
that should init the spring:
#PostConstruct
public void init(){
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
svrFactory.setServiceClass(MyWebService.class);
svrFactory.setAddress("http://address.com");
svrFactory.setServiceBean(wsHandler);
svrFactory.getInInterceptors().add(new LoggingInInterceptor());
svrFactory.getOutInterceptors().add(new LoggingOutInterceptor());
svrFactory.create();
}
Please tell me if it solve you problem....

Categories