How to get the session object of an EJB session-bean like session object in JSP(web layer)?
Because I want to add an attribute to the session and use it later in its process.
Regards
In the web layer you get the session with
request.getSession()
This returns the session object tied to this request. Here you can store session specific attributes you can reuse on subsequent requests.
In the EJB layes you have completely different session objects which have nothing to do with the session above. There are Stateless Session Beans and Stateful Session Beans. Stateful session beans can also keep state over multiple requests however they are very tricky to work with and are only useful for a very limited set of use-cases. Stateless Session Beans do not keep (outside detectable) state between calls, so are useless to store attribtes you want to reuse later, unless you store them in a persistence layer or a cache.
In most cases the easiest to work is to keep the conversation state in the request session object and pass the attribute you want to reuse later from the web layer to a stateless service bean as a parameter.
Related
It's as simple. In Spring MVC, how and where do I store a complex java object so that it is available across the action servlets. For example if an ajax is called on next page, the business object from within some previously called servlet, stored somewhere should be accessible in that ajax action method in java. I did this by creating a singleton bean but it failed when multiple users hit the application. User outputs are affected among each other. I need to achieve this in a non-singleton manner.
You can store objects in your request object:
request.setAttribute("key", valueObject);
To get the object, simply use
request.getAttribute("key");
Or, as Subir Kumar Sao said in the comments, use the session to store your stuff:
request.getSession().setAttribute("key", valueObject);
and
request.getSession().getAttribute("key");
You can use either
request.setAttribute("key", valueObject);
request.getAttribute("key");
or
session.setAttribute("key", valueObject);
session.getAttribute("key");
Difference between them : Request-scoped attribute is visible only while current request is processed. Session-scoped attribute is persistent between several requests from the same user.
You should keep your objects on session level. As long as the session is alive, you can access your session level variables, regardless of the requests.
request.getSession().getAttribute("key");
request.getSession().getAttribute("key", value);
Keep in my mind that once a session level attribute is set, that is always there until, session is killed or invalidated. So you may need to remove the attribute according to your logic.
request.getSession().removeAttribute("key");
I have been reading about Stateful and Stateless session beans and came across a sentence that states that:
Stateful session beans cannot be exposed as web services.
Can anyone elaborate why ?
Every Stateful bean instance located in the EJB Container has an unique object identity.
From spec.: 3.4.7.1 Stateful Session Beans
A stateful session object has a unique identity that is assigned by the container at the time the object is created.
In order to use a Stateful bean, the client code needs to get a Stateful reference from the EJB Container.
This reference has to be used to make every future request.
Due to the reference object knows the identity associated to the stateful bean, you can be sure that all requests that participate in the "conversation" will be resolved for the same instance bean. This means that the Client has an important role in achieving the stateful behavior.
The SOAP protocol doesn't provide a way that allow to store in a web service client this identity, therefore, if the client doesn't know which stateful instance has the conversational state, every request will be processed by different ejb (such as the case of stateless).
This is because, typically, state does not required to maintained across web service client calls. Moreover, SOAP-based web services are inherently stateless in nature. If you need to maintain state across web service calls, stateless beans can be used to persist state (although this degrade application performance)
I am trying to implement "remember me"/"autologin" functionality. I have stored a cookie at the client but when should I read it? If I try to do that in a filter, for example, I won't have access to my application-scoped beans which I use to access the db.
What are the best practices to do that?
It depends a little on how your current login exactly works. Is it a container login followed by custom stuff (like putting some object in the session) or only custom?
In the first case you can't do an auto-login completely in JSF, since the container will kick-in whenever the uses tries to access a protected resource. In that case you still need to do the container login part in a Filter (HttpServletRequest#login).
For both the first and second case, the JSF part can be done via a global PhaseListener. In this case you could listen to a very early event, e.g. before RESTORE_VIEW. In this event handler, you can check the session for whatever object your put in there to flag your login, and if it's not there use the HttpServletRequest to check if there's a "remember me" cookie and proceed with the login if needed. When the PhaseListener is called, JSF is fully operational and you can access your application scoped managed beans.
If you only use an object in the session and don't bother doing any container login, then you can simply skip the first part.
p.s.
Another option is not to put any DB stuff in JSF managed beans, so you don't need JSF operational in order to access your DB. In a Java EE application, EJB beans are alternative candidates (and actually better suited for this job). They can be injected into your filter and used to access the DB before the JSF life-cycle starts. Next to EJB beans, CDI beans are also an option. In many ways, these are better alternatives for JSF managed beans anyway.
Session scope will keep content for as long as a session is active, combine it with a state persistence either in DB or via a cookie.
Non of the scopes will really "remember" your state by itself, the best you can do is persist the state to the DB and when the user returns, restore it as best as possible and push the data into a sessionscoped bean.
Otherwise extend the sessionscope's session via a cookie
FacesContext.getCurrentInstance().getExternalContext.addResponseCookie(..)
Im really new to java, jsf, jsp, and I need to learn how it works quickly. So the website Im using to practise has some terms etc that I dont know what they mean and Im hoping somebody can explain what they mean and how/what they are used for:)
Requestscoped
Applicationscoped
Sessionscoped
EntityManager
and could someone walk me through what these lines do?
#RequestScoped
public class Dao {
#DataRepository
#Inject
private EntityManager entityManager;
First of all, in Java (5 and higher), "things" starting with a # (e.g. #Deprecated) are called annotations.
Annotations provide data about a
program that is not part of the
program itself. They have no direct
effect on the operation of the code
they annotate.
Your JavaBeans needs to be configured to a scope if you want to use it in JSF (Definitions can be found here).
#RequestScoped: Objects with this scope are visible from the start of the request until the end
of the request. Request scope starts at the beginning of a request and ends when the
response has been sent to the client. If the request is forwarded, the objects are visible
in the forwarded page, because that page is still part of the same request/response
cycle. Objects with request scope can use other objects with none, request, session,
or application scope. If you have to think it in terms of servlet, the managed bean is stored in the HttpServletRequest until the end of the request (when the response is sent to the client). After that, the bean no longer exists in the request.
#SessionScoped: An object with session scope is visible for any request/response cycle that
belongs to a session. Objects with this scope have their state persisted between
requests and last until the object or the session is invalidated. Objects with session
scope can use other objects with none, session, or application scope. Basically, these objects are stored in a HttpSession (refer to Servlets again). Each session has a session ID (known as JSESSIONID) that the bean is associated with.
ApplicationScoped: An object with application scope is visible in all request/response cycles
for all clients using the application, for as long as the application is active. In terms of Servlet, this could be, managed bean stored in a ServletConfig.
#NoneScoped: Objects with this scope are not visible in any JSF page. When used in the configuration file, they indicate managed beans that are used by other managed beans in the application. Objects with none scope can use other objects with none scope.
For EntityManager, this is associated with persistence context. It is used to create and remove persistent entity instances, to find entities by their primary key identity, and to query over all entities. For more, refer to the JPA (Java Persistence API) Specification, or Hibernate.
#Inject, means that the instance is injectable. They follow the infamous crase word of Depency Injection or Inversion of Control (IOC). What this basically mean, is that when the resource (in your case EntityManager entityManager is needed, the JEE container instantiates the resource for you (without you needed to instantiate it directly through e.g. a constructor, etc.).
I have no clue what #DataRepository means. Never seen it before.
I hope this helps you.
These terms are usually associated with a dependency injection framework like guice and not with java in particular.
http://code.google.com/p/google-guice/wiki/Scopes describes the various scopes that are built into guice.
By default, Guice returns a new instance each time it supplies a value. This behaviour is configurable via scopes. Scopes allow you to reuse instances: for the lifetime of an application (#Singleton), a session (#SessionScoped), or a request (#RequestScoped). Guice includes a servlet extension that defines scopes for web apps. Custom scopes can be written for other types of applications.
I've some session scoped state. First idea to hold it was session scoped servlets. So I bind my servlet like this
bind(Foo.class).in(ServletScopes.SESSION);
But I get an exception
javax.servlet.ServletException: Servlets must be bound as singletons. Key[type=Foo, annotation=[none]] was not bound in singleton scope.
So servlets can't have scope from ServletScopes? Whats the right way to deal with session state (yeah, of course it's better to write state less servlets/classes/applications)?
From my understanding you can bind whatever you want to the session scope, the problem is that in your example Foo seems to be an subclass of Servlet, and Servlets must be bound in Singleton scope.
To resolve this, just bind your state (called Bar) in session scope and give your Foo constructor a Provider<Bar> argument (which will be filled in by Guice) so you can access the session-scoped state from the singleton-scoped Foo Servlet.
servlets are not created by Guice, but by the servlet container. And they are singletons : only one instance is created by the servlet container to serve all the requests of all the clients.
So binding them to session scope has no sense : Guice can not create one different servlet instance per session.
A servlet should always be stateless (i.e. its state should be global to all the clients, and be accessed in a thread-safe way)