I've got a service layer which is managed by spring. Now at one point I need some informations from the httpsession. Is there a clean way to inject the httpsession directly into my servicelayer?
My portlets are not managed by spring - this point matters in my setup.
Bad idea.
The service layer shouldn't have to know anything about HTTP.
My advice is to pull the information out of the session, bind it to a (validated) object, and make that object a parameter for one of the method calls on your service's interface.
This is NOT the place for injection.
Related
Our application consists of web pages that interact with backing beans and Stateless EJB services, but there is also a remote client that interacts with the Stateless EJB services.
Many of the services query the DB and then filter the result set based on the current user/caller (for example, users have permission to view only some record types); that is, they use programmatic rather than declarative security.
On the web side, my intuition would be to store the currently logged-in user in a SessionBean, but I want the Stateless EJB services to filter the result set based on the currently logged-in user so that the filtering also applies during remote client calls. I can inject a SessionBean into a Stateless EJB service, but I think SessionBeans use HTTP sessions, and as there is no HTTP session during a remote client call, I don't see how that could work.
I sense that my approach is wrong, and that I should be retrieving the "Principal" from the container; however, due to our application's development lifecycle, container-managed security is not set-up yet, but I am still tasked to implement the business logic responsible for filtering records now rather than later.
My closely-related questions:
Can a SessionScoped bean be injected into a Stateless EJB knowing that the Statelesss EJB will be invoked by remote clients? What is the value of the SessionScoped bean in that case?
Instead of a SessionScoped bean, should my backing beans and Stateless EJB services be retrieving the Principal from the container?
If yes, how can I substitute a mock Principal to work on the business logic until container-managed security is set-up?
p.s. I am new to Java EE.
Technology:
Java EE 6
GlassFish 3.1.2.2
"Backing bean" e.g. javax.enterprise.context.SessionScoped
"Stateless EJB services", e.g. javax.ejb.Stateless
"remote client"; i.e. some non-web clients invoking the Stateless beans directly (through EJB/RMI)
Update:
More detail on the "remote client". I'm not sure how to word this because I'm new to Java EE, but this "remote client" will not be over HTTP. Another application, let's call it application X, will receive XML messages from clients. I think they authenticate the client using certificates. Application X will transform the XML into POJOs and call my Stateless EJB services directly.
In this case, I think I'm right to say that I should not inject a SessionBean into a Stateless EJB service because there will be no HTTP session when the EJB service is called by Application X. Is my understanding correct?
Thank you for your patience. I am aware of my ignorance in these matters.
You are not fully clear with your questions. Your question let me assume a lot. So you should break your questions down and provide more details to your issue.
First of all you should mention which Java EE version you are using. Anyway here my details with some assumptions to your context.
Assuming you are talking about following
Backing beans: http://docs.oracle.com/javaee/5/tutorial/doc/bnaqm.html
"Stateless beans" == Stateless session beans : http://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html#gipin
SessionScoped beans : http://docs.oracle.com/javaee/6/tutorial/doc/gjbbk.html
"remote client interaction": http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html#girfl
In the case of the major question, you should keep in mind to separate the Http session from your Stateful session bean: Stateful Session Bean and HTTP Session
So if you try to couple Http Session with a Stateful session bean you have to provide the http session details into a area where both http session and stateful session bean can access the data and also hold a reference to it.
This assumes also, that your remote EJB service will not create a http session first. So you will not have a valid reference to a HTTP session via remote EJBs.
If you are using a HTTP based "remote client interaction", why are you not creating a http session on the first request?
HttpServletRequest.getSession(true)
will ensure what you will always get a valid session
If you are using some other HTTP bases frameworks like jax-rs there are also options to get a http session there.
Update 1
Can a SessionScoped bean be injected into a Stateless EJB knowing that
the Statelesss EJB will be invoked by remote clients? What is the
value of the SessionScoped bean in that case?
You can use the backing beans as POJOs in your EJBs, but not as http session scoped beans. If you need them from remote EJB you have to initialize them first, before using. Means, the have no value on remote EJB calls.
Instead of a SessionScoped bean, should my backing beans and Stateless
EJB services be retrieving the Principal from the container?
Also here the question is not fully clear.
You can configure your container (glassfish) to use have manual user, roles and realms. So this is your local mock for the Security and you can retrieve the Principal from the container.
http://docs.oracle.com/javaee/6/tutorial/doc/bnbxj.html#bnbxs
Independently: I would recommend you to read the Oracle tutorial about Java EE. It is pretty good. Taking some dollars I would recommend Java EE 7 Essentials
The new JSR 299 "Contexts and Dependency Injection for Java EE" seems to be based on the concept of "Scope".
The beans are created and associated to one of the supported Scopes: Application, Session (mapped to a HTTP session), Conversation, and Request.
Does it make sense to use CDI if there is no HTTP Session (for example, an Enterprise application that exposes functionality through EJBs remoting) since the Managed Beans are not going to be associated to any Context (since they do not exist)?
Is it even possible to use CDI in such an scenario? Which advantages would it bring to it?
It reminds me of my own question I asked some time ago: How does #SessionScoped work with EJB? Is CDI only for web-tier?
It seems that the idea of 'scope' is relevant only in the case of HTTP Session.
However, I can see a valid use of the #ApplicationScoped scope as a way to implement an application-singleton bean, despite if the request is a HTTP one.
Javadoc says:
The application scope is active:
(...)
during any Java EE web service invocation,
during any remote method invocation of any EJB, during any asynchronous method invocation of any EJB, during any call to an EJB
timeout method and during message delivery to any EJB message-driven
bean,
You can also create your own scopes. CDI is very extensible and can be used in a variety of situations. It's also being used in SE applications where there is neither an HttpSession nor HttpRequest.
Apart from that, CDI is not only for Lifecycle managment, you can use it to do dependency injection thus separating interfaces from their implementations in a very clean way. You can also perform some AOP techniques using interceptors and decorators, or build a very loose-coupled Observer pattern by taking advantage of CDI Events.
I have a webapp on one Glassfish server (front-end) and an EJB 3.1 app (back-end) on another Glassfish server. The webapp communicates with the EJB 3.1 via remote invocation.
I would like to pass context data (user data i.e.) without having to define it as an input parameter of each business operation.
I have one idea, but not sure it will work: use a ThreadLocal to store data, but the ThreadLocal will only be available on one server (meaning JVM) => use the InvocationContext object and create interceptor to add user data to the ContextData Map.
What do you think about it? Any other ideas are more than welcome! ;-)
UPDATE
After first answer, I googled it a little bit and found the annotation #CallerPrincipal.
How can I set this object before the remote invocation?
The container will already handle this so you don't have to code it yourself.
In your EJB, you can access the EJBContext, which has a getCallerPrincipal() method which will give you the callers identity.
I am writing a Spring web application in Eclipse. In WEB-INF I have a web.xml file that gives a servlet mapping for a myapp-servlet.xml file.
In myapp-servlet.xml, I have a bean for a page controller. I surmise that the Spring DispatcherServlet instantiates these beans from its own ApplicationContext. When I run my project as a server, it displays the index.jsp file - "hello hello hello".
Now I also surmise that were I to put a submit button that sends post data in this index.jsp file, my page controller would be notified of the HTTP request. However, how can I interact with the rest of my application (the business layer) from the page controller? I am writing an LDAP Directory Lookup application, and once the user inputs a name I want to return an email. So, when the user inputs a name and hits submit, I want to communicate with my LDAP business layer. How can I do this?
One way I have thought of doing this is to add my business objects as properties to the page controller in the myapp-servlet.xml file. However, this seems to integrate the business layer and the controllers far too much for my liking - it means that every controller would need properties for business objects.
Another way I have thought of doing this is to create a kind of factory that all controllers have listed as a property in their XML. Through this factory, the controllers can access business objects; the factory is the interface between the two layers.
These are both custom ideas, and I suspect that there is a pre-made solution. Is there already a method of going about this? (Integrating business layer with web / page controller layer?) Or is it up to the programmer to concoct a custom solution as I outlined above?
Thanks, (and sorry for the long question - hence the bold)
ktm
Your controller needs to somehow hold a reference to your business objects. To fully benefit of Spring, you will want to inject those dependencies into your controller.
This is not tight coupling, especially if those business objects implement an interface and your controller will only know about that interface.
Dependency injection eliminates the need for factories as you will need to know about the service interfaces with our without a factory:
SomeBusinessServiceInterface service = businessFactory.getBusinessService();
But think about it like this: you must somehow get a reference of some service (using that service interface for low coupling) and most likely you need to cache that -- store it as an instance variable. Since you have that anyway, providing a setter does not couple your web and business tier any more than they already are.
If a setter seems unnatural (and it sometimes is) use constructor injection to implement this as classic OO aggregation.
Regarding the application context config, Spring allows you to define a webapp-wide application context defined using a ContextLoaderListener in web.xml. This is usually where all your business bean definitions should reside. Your -servlet.xml application context is bound to the servlet and should usually contain MVC stuff, referencing the beans in the root context as that context automatically becomes the parent of all the -servlet.xml (therefore all the beans there are visible for your servlets).
I am using the JAX-WS "WebService" annotation on a class to expose its "WebMethod"s as a web service. The class is denoted as the servlet class handling calls to "/MyService".
As essentially a servlet, I would expect an instance of this class to be created once and to basically be a singleton. I have code in the constructor of this class to create an EntityManagerFactory for assignment to a member variable. What I'm seeing is that the constructor is being called for every client request to the web service. This is not good.
Does anyone know what's going on here? Does anyone understand what I'm trying to ask? :)
Thanks.
As essentially a servlet, I would expect an instance of this class to be created once and to basically be a singleton.
It's up to container. You cannot rely on it.
Create a real singleton -- a simple Java class -- which does all the heavy lifting, and call it from the servlet.
Your topic mentions a SLSB, which I assume is "Stateless Session Bean". In Java EE 5 you can create web services either from a Stateless Session Bean, or you can annotate a class and the runtime will publish it as a webservice when deployed in a compliant web container.
In either case, neither of these are Servlets per se, and don't follow a Servlet lifecycle.