Implementing a simple Login screen using JSF and Spring and Hibernate. I have written the Service and Data Layer Beans in Spring and integrated them with Hibernate.
I defined a Sign Up (new User creation) screen with two fields user id, password in JSF and wired them to a Managed Bean. (Bean Name: Users) Here this bean is also the domain class.
Now on click of the create button in JSF view I need to call the Service Bean methods (which are spring beans). For this I see that I have two ways to do,
Write a method in Users managed bean that takes the given user, password and calls the spring service bean methods which in turn calls DAO bean methods for saving data in DB. But here my question is how far it is a good practise to write controller kind of method in Domain classes?
Second way is to define a new Managed Bean that has the Spring Service object as a property (Which is injected using spring+jsf integration) and a method to call the service bean methods.
Am I doing a correct design? Any thing wrong? Please suggest me for a better design.
Thanks
Dont make your domain class as jsf managed bean.
Generally what I follow is I encapsulate domain class and other UI supporting properties in a form bean(when scenario is complex else direct entity as a property in managed bean) and have it in managed bean.
Spring service is injected in managed bean and on action form bean/entity bean is passed to spring service for business/use case processing and persistence(dao/repository).
Template Code:
#ManagedBean
public class Bean{
private Entity entity;//or
private FormBean formBean;
#Inject private Service service;
public String doAction(){
//error processing from service layer and UI message handling
service.process(entity);//or
service.process(formBean);
return Navigation.Constant;
}
}
Managed bean purpose should be to collect view data and pass it to service for processing. If you make your domain/entity class as managed bean you will be coupling it with JSF library which is not good for reusability. As per design principle SRP(single responsibility principle), class should have one responsibility in that case it will have more and hence as mentioned above not good practice.
Point 2 as mentioned by you is better.
Hope this helps !!!!
Related
I would like to know which is good practice. For example, I have Person pojo for Entity Class,PersonService EJB stateless session bean for persisting Person class and indexBean(CDI request Scope bean)for binding with JSF to create Person class. Is it good to create new Person Object in indexBean instead of using #Inject?
If not, could you show me how should i design for this scenario? Thanks.
According to the CDI documentation of weld, you should not inject Entity beans:
According to this definition, JPA entities are technically managed beans. However, entities have their own special lifecycle, state and identity model and are usually instantiated by JPA or using new. Therefore we don’t recommend directly injecting an entity class. We especially recommend against assigning a scope other than #Dependent to an entity class, since JPA is not able to persist injected CDI proxies.
You can find further information here.
You shoud create a new Person object / or load it from Database (by your PersonService) in your indexBean, depending on your usecase. Also the persistence of the Person entity will finally be done by your PersonService.
I need to call a method annotated with #Asynchronous in EJB from a ConversationScoped bean. Inside this method I create instances of some classes using #Inject to inject ConversationScoped beans.
Is it somehow possible to set the context of the asynchronous method to given Conversation?
I hope you can help me.
No, absolutely not. EJBs do per definition not run in web container, but in EJB container. In essence, having any web-related artifact/dependency (including javax.faces.* classes) inside an EJB class is a red alert. You're not supposed to inject/access any class from the client tier (the WAR) in the business tier (the EJB/EAR). Moreover, conversation scoped beans are tied to a HTTP request parameter and this information is nowhere available in an EJB container.
Whatever problem you're trying to solve and for which you incorrectly thought that this all would be the right solution, it has to be solved differently. As an educated guess, I think you just need to let the EJB fire a CDI event or take a callback argument.
See also:
JSF Service Layer
I'm converting some code to take advantage of EJB 3 and I've come up with a scenario where I have a #Stateless EJB being injected into JSF Managed bean that is annotated with #SessionScoped.
I was wondering how this effected the life of the EJB? Does it remain stateless and get destroyed after each call to one of its methods or does the same bean exist for the duration of the session?
As stateless EJB session beans are pooled by the server, there is no direct relationship with their lifecycle and the lifecycle of other session scoped beans.
The webserver creates and destroys such beans when it needs to.
From the EJB spec:
The container can perform the instance creation at any time—there is no direct relationship to a client’s invocation of a business method or the create method.
For more information see the specification (around page 99).
Actually I'm new to JSF and Facelets and enterprise apps despite i've been working on it the last 4 months, anyway, i'm developing a web page which has a login, an user administrator and a documents administrator (it has more but it doesn't matter) and i have to manage the acces and the content of pages according to each user permissions. Reading about security i've found out many ways of doing a login, but i have made my own with Stateful Beans in order to maintain the users data in the application for using them later so i can restrict the content. the question is... is this the correct way to manage the content according to users restrictions?
if not, which is the best and securest way of doing it?
this is my Stateful Bean (i did not include the Getters and Setters)
#ManagedBean
#Stateful
public class HandlerLogin implements Serializable{
#EJB
private LoginMethodsLocal loginMethods;
private String loginNickname;
private String loginPassword;
private String userData[];
//[0]=Nickname
//[1]=Name
//[2]=User Type
private boolean loguedIn= false;
public void check(){
System.out.println(this.loginNombre);
System.out.println(this.loginContrasena);
this.userData= loginMethods.Login(this.loginNickname, this.loginPassword);
//the method loginMethods.Login() queries in the database looking for
//"this.loginNickname" and "this.loginPassword"
if (this.userData!=null){
this.loguedIn=true;
}
else{
this.loguedIn= false;
FacesContext.getCurrentInstance().addMessage("mensajesLogin", new FacesMessage("Error, User Does not Exist"));
}
}
public void closeSession(){
this.userData=null;
}
}
so my logic to manage the content and navigation is to check what kind of user is and depending on it determine how the acces and rendering is going to be
The #Stateful annotation does nothing in a JSF #ManagedBean. That annotation is only really been used when the class is by itself injected as #EJB in another managed bean or EJB and even then, a brand new and completely different instance with all properties set to default would have been created and used. So the #Stateful annotation definitely doesn't do what you think it does. Remove it, it makes no sense in this context.
Whether the remaining code is the correct way or not depends on the concrete functional requirements. There are many ways which are equally good and secure (assuming that you understand what code you actually are writing). The question is more: how many of the wheel do you want to reinvent yourself? The builtin container managed authentication leaves very little room for finegrained control, but if it is sufficient for you, then just make use of it instead of homebrewing the authentication yourself.
Going through the following related answers should give some good ideas:
Performing user authentication in Java EE / JSF using j_security_check
JSF: How control access and rights in JSF?
How to check if is user logged in?
How to properly use isUserInRole(role)
JSF request scoped bean keeps recreating new Stateful session beans on every request?
I want a method in a session scoped backing bean to be called after a user logs in. How can I do that?
Environment: Spring Security 3.0.x, Spring 3.0.x and JSF 1.2. The backing beans are managed by Spring.
Background: Sessions are created even without login. My session scoped bean holds settings, that are initially set to default values. After login I want to update the session state to the preferences stored in the database for that particular user. To achieve that I imagined an interface or even simpler an annotated (e.g. #PostLogin) method, but so far I have not found anything like that.
It would be OK if that method is called on every principal change, i.e. also on logout. It would also be acceptable if the whole bean is destructed and recreated on login, though my other session scoped beans should survive.
What I have found so far is:
ApplicationListener<AuthenticationSuccessEvent>: The listener apparently needs to be application scoped, and I can't get access to my session scoped bean in it. #Autowired plus scope proxy don't work. The injected object is broken; it does not contain its dependencies although the real backing bean does.
<form-login authentication-success-handler-ref="..">: haven't tried this, but I need the method to be called independent of the used login procedure. Other than form based we support remember me and programmatic login (e.g. automatically logged in after password forgotten process).
Answering my own question:
ApplicationListener was the right track, however #Autowired was not.
I defined an interface with one method, that is implemented by my session scoped bean. The (singleton scoped) event listener class then uses ApplicationContext.getBeansOfType(..) to find the session beans by that interface and invokes the interface's method on each of them.