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(..)
Related
I have no code done yet but I'm thinking on how I'm supposed to do this in JSP/JSF.
So, I have some classes I was thinking I could load from a DB whenever the session starts. My first idea is that I just load them once with the necessary data from the DB, do all the operations, and then destroy the bean when the session is done. The problem is, what if another user changes information during the session? So I thought I could use a page scope, however I don't want to overload the server.
What's the best practice on this?
Firstly, each visitor to your app gets their own session-scoped bean, so you've only got to worry about persisting each user's changes to the data on the bean.
Secondly, you are worrying about matters which are taken into consideration by ORM offerings. Using the API provided by something like Spring JPA or Hibernate will present you with controls for persisting data changes back to the DB via a local handle on a Bean.
I decided to use an application scoped bean instead of a singleton class. That will do.
I need simple, preferable session based cache, for our Spring MVC 3.1 app. I know in 3.1 introduced cashing abstraction, but as far as I know, it is application wide caching. We need something simpler, for caching user grid data. I don't mined even using it directly, as long, as it has simple interface.
Any one used something like that? Is there any good lib? Or is there way to force Spring cache abstraction to cache data for current session only? Or am I doomed to write it by myself?
Session scoped bean
If you don't mind explicit solution, create a bean with session scope and inject it to your controller.
If you don't forget to wrap it with scoped proxy (<aop:scoped-proxy/>) you can
just place your cached data in fields of that bean. Spring will automatically create one instance of that bean per each HTTP session and store it there.
Caching abstraction
On the other hand I think Spring caching abstraction might work for you - SPeL gives you access to HTTP environment so you probably construct cache key declaratively (in annotation) based on current user session id or some other attribute like user name.
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 am using a JEE6 stack including JPA 2.0, JSF 2.0, EJB 3.1 etc.
The way my architecture is setup is the following:
I have JPA annotated DAOs using hibernate as my JPA provider.
I have JSF Managed beans which correspond to my facelet/xhtml pages.
I have EJBs that handle all of my database requests.
My XHTML pages have JSF EL which make calls to my Managed beans. My managed beans contain references to my DAO entities which are managed by EJBs. For example, I have a user entity which is mapped to a db table. I have a user EJB which handles all CRUD operations that return Users. I have a page that edits a user. The highlevel workflow would be: navigate to user edit page -> EL calls a method located in the managed bean that loads a user. The method calls userEJB.loadUser(user) from the EJB to get the user from the database. The user is edited and submit -> a function is called in the managed bean which calls a function in the EJB to save the user. etc.
I am running into issues accessing my data within my JSF pages using EJBs.
I am having a lot of problems with lazy initialization errors, which I believe is due to how I have set things up.
For example, I have a Client entity that has a List of users which are lazily loaded. In order to get
a client I call a method in my EJB which goes to the database, finds a client and returns it. Later on
i wish to access this clients list of users, in order to do so i have to go back to the EJB by calling some sort of method in order to load those users (since they are lazily loaded). This means that I have to create a method such as
public List<User> getUserListByClient(Client c)
{
c = em.merge(c); return c.getUserList();
}
The only purpose of this method is to load the users (and I'm not even positive this approach is good or works).
If i was doing session management myself, I would like just leave the session open for the entire request and access the property directly, this would be fine as the session would be open anyway, there seems to be this one extra layer of indirection in EJBs which is making things difficult for me.
I do like EJBs as I like the fact that they are controlled by the container, pooled, offer transaction management for free etc. However, I get the feeling that I am using them incorrectly, or I have set up my JSF app incorrectly.
Any feedback would be greatly appreciated.
thanks,
If i was doing session management
myself, I would like just leave the
session open for the entire request
and access the property directly, this
would be fine as the session would be
open anyway
Indeed, that's the open session in view pattern (also called open EntityManager in view). It can be used with EJB as well. Ideally, the transactions should be managed in the business layer/EJB so this can be seen a slight deviation from the pure layer architecture. But it solves the problem of lazy loading in the view and is easy.
Otherwise, you must make sure to eagerly load the information that will be used after the transaction is over. Or you may rely on DTO, but then it starts to be cumbersome.
Here are two more links that cover the topic and discuss pros/cons and alternatives:
SO question: Open Session In View Pattern
Xebia blog: JPA implementation patterns and especially this one
Your usage seems good. Just remember that em.merge(c) may save the changes made to Client c into the database. If you just want to get the UserList of Client c without saving the changes made to the Client c, then you can do this:
public List<User> getUserListByClient(Client c)
{
Client client = em.find(Client.class, c.clientId);
return client.getUserList();
}
Or better ,just send the Client Id to the getUserListByClient instead of passing a full Client object , just to save a tinsy winsy bit of memory :)
First off, I think I'm trying to use Spring incorrectly, but confirmation would be appreciated.
I am trying to reset a single bean in mid-application. My initial configuration works just fine.
My scenario
1 Insurance Claim bean (session
scope)
1 Claim details bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope)
1 Claimant details bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope)
1 Submit claim bean which is a
multiactionController
(getClaim&setClaim enabled, prototype
scope).
My application is more complex than this, but for the sake of providing a clear example I wont describe the whole thing.
The first two controllers are used to set various properties of the claim, validate etc.
The third writes a claim to the database. THEN I want it to reset the bean. However I can't just say claim=new Claim() in SubmitClaimController.OnSubmit() as the ApplicationContext keeps its reference to the old Claim.
I could just create a method Claim.clear(), but that feels like the wrong approach. However, I can't see anything like ApplicationContext.destroyBean(beanname) or ApplicationContext.createBean().
I do not want to refresh the entire ApplicationContext as I will have other beans I want to keep alive throughout the session.
Thanks in advance.
I don't think the Claim object should be Spring-managed. It's really not injected; sounds like it should be bound from the request sent into the controller and passed to the service for processing. If you put a Claim into session scope, you need to invalidate the session when the transaction is done or if the session times out.
By the way, I see you mention three controllers, but no service. You should have a service layer, and controllers should not deal with DAOs or persistence.
You can change the scope of a bean. Default is singleton which is sometimes not appropriate in web contexts. You can change it to be session scoped by adding for example
the attribute scope="session"
and the child <aop:scoped-proxy proxy-target-class="false"/>
to the bean definition.
I am working with 3.0M4, btw, but I would expect it to be in earlier versions, as well, as it's a very important functionality. Have a look at:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ch03s05.html
Cheers!