I am setting a value in the login-bean when the user logs-in
using
--Login-bean
setMailNickname(mailnickname);
And in the info page I am able to retrieve the same value using
--InfoPage
<h:inputText value="#{login.mailNickname}" />
Now on the info page I am taking some more info from the user and saving all of them in the database, As one of the value is from the login form bean it is prepopulating on the Info-page but how to assign the same value to the info-page bean variable-
InfoBean.mailNickname
so that it can be saved into the database with the other fields which the user provides.
How can I assign the value to the infopage bean variable?
You can inject LoginBean into InfoBean, so that you can have a reference to its fields. As I understand one of your beans is at least #SessionScoped. You didn't provide that information, so I'd go as far as to guess that LoginBean is used for logging into your application or something like that and InfoBean to hold that information for future reference. Following that chain of thinking your InfoBean would look like that:
#ManagedBean
#SessionScoped
public class InfoBean {
private String mailNickname;
public String getMailNickname() {
return mailNickname;
}
public void setMailNickname(final String mailNickname) {
this.mailNickname = mailNickname;
}
// other fields, methods...
}
and your LoginBean then would hold reference to session-scoped InfoBean:
#ManagedBean
#ViewScoped
public class LoginBean {
private String mailNickname;
public String getMailNickname() {
return mailNickname;
}
public void setMailNickname(final String mailNickname) {
this.mailNickname = mailNickname;
}
#ManagedProperty("#{infoBean}")
private InfoBean infoBean;
public void setInfoBean(final InfoBean infoBean) {
this.infoBean = infoBean;
}
/** Method you use for populating */
public void populateInput(final String mailNicknameFromDb) {
setMailNickname(mailNicknameFromDb);
infoBean.setMailNickname(mailNicknameFromDb);
}
}
Remember about getters and setters for those fields as well as setter for managedProperty and be careful about scopes (you can't for example inject request-scoped bean into application-scoped bean, because the request-scoped one would probably not exist yet when creating application-scoped one).
Related
I am tring to implement logging of users in Spring Security on the basis of a popular Tutorial and have a doubt about how spring beans are wired.
The below class is defined as a standard bean in the Spring Context
public class ActiveUserStore {
public List<String> users;
public ActiveUserStore() {
users = new ArrayList<String>();
}
public List<String> getUsers() {
return users;
}
public void setUsers(List<String> users) {
this.users = users;
}
}
The above is defined as a Bean through
#Bean
public ActiveUserStore activeUserStore(){
return new ActiveUserStore();
}
And the Bean is being used in the below class, please note the users.add(user.getUsername());
#Component
public class LoggedUser implements HttpSessionBindingListener {
private String username;
private ActiveUserStore activeUserStore;
public LoggedUser(String username, ActiveUserStore activeUserStore) {
this.username = username;
this.activeUserStore = activeUserStore;
}
public LoggedUser() {}
#Override
public void valueBound(HttpSessionBindingEvent event) {
List<String> users = activeUserStore.getUsers();
LoggedUser user = (LoggedUser) event.getValue();
if (!users.contains(user.getUsername())) {
users.add(user.getUsername());//HOW IS THIS SAVED TO THE ACTIVEUSERSTORE BEAN
}
}
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
List<String> users = activeUserStore.getUsers();
LoggedUser user = (LoggedUser) event.getValue();
if (users.contains(user.getUsername())) {
users.remove(user.getUsername());//HOW IS THIS SAVED TO THE ACTIVEUSERSTORE BEAN
}
}
My Question: Since users variable belongs to the ActiveUserStore Bean, how does the following line of code inside the valueBound and valueUnbound methods of Logged User Class, automatically save the ussers data inside the ActiveUserStore Bean ?
users.add(user.getUsername());
I have also marked this line in the code snipped above for clarity.
Any help is appreciated, since I think my understanding of how Beans are wired and used is probably not clear since I am not able to understand the above working. Thanks.
Think about Spring Bean as usual Java class. This class instantiated by Spring at application start just once (actually this is not always true, but by default it is)
Now you inside of your bean, you have reference to List variable and get it with:
List<String> users = activeUserStore.getUsers();
Now users variable contains reference to the List stored in bean. This is because in Java objects are passed by reference.
LoggedUser user = (LoggedUser) event.getValue();
if (!users.contains(user.getUsername())) {
and here users variable contains List class reference. List class have method add, and LoggedUser have getUsername method. As users variable refers to same List object as your bean property contain, this adds username to your bean:
users.add(user.getUsername());
}
Given a class A:
public class A {
private String foo;
//getter, setters etc...
}
can one reference the foo property if an A object itself is exposed as property in a managed bean, e.g:
#ManagedBean
public class SomeBean {
private A a;
//getter, setters etc...
}
#{someBean.a.foo}
Indeed, it will work. Both for setting and obtaining the value. An input such as:
<h:inputText value="#{someBean.a.foo}" />
will both obtain the value to display it and set the new defined value by doing either
beanInstance.getA().getFoo();
or
beanInstance.getA().setFoo("newValue");
Just take into account that for this to work and avoid getting a NullPointerException, getA() cannot return null, meaning that your a object must be instantiated.
When or where do entities get created?
Do they get created when the XHTML page loads and accesses the entities via the managed bean?
Or do they get automatically created in the managed bean?
Do we need to manually create it from the managed bean's constructor?
Please see the code below (some necessary code might not have been copied.)
The entity would be:
public class PersonalInfo implements Serializable {
#Size(max = 50)
#Column(name = "FIRST_NAME", length = 50)
private String firstName;
// some getters and setters
}
the web page would be:
<h:form>
<h:outputText value="first name"/>
<h:inputText value="#{personalInforController.personalInfo.firstName}" />
<h:commandButton value="hit me"
action="#{personalInforController.create}"
immediate="true"/>
</h:form>
and the backing bean would be:
#Named(value = "personalInfoController")
#SessionScoped
public class PersonalInforController {
#EJB
PersonalInfoFacade ejbFacade;
PersonalInfo personalInfo;
String defaultPage = "index";
public String create() {
try {
ejbFacade.create(personalInfo);
return "prepareCreate";
} catch (Exception e) {
return "success";
}
}
}
In the example code given, the create action indeed doesn't seem to be able to work. The entity must be created by the backing bean before that.
If it's a simple entity, either the constructor or an #PostConstruct method would work. For instance:
#Named(value = "personalInfoController")
#SessionScoped
public class PersonalInforController {
#EJB
PersonalInfoFacade ejbFacade;
PersonalInfo personalInfo;
String defaultPage = "index";
#PostConstruct
public void init() {
personalInfo = new PersonalInfo();
}
public String create() {
try {
ejbFacade.create(personalInfo);
return "prepareCreate";
} catch (Exception e) {
return "success";
}
}
Some notes about the code. It's highly suspicious, and most likely plain wrong, to declare your bean to be #SessionScoped. If personalInfo is being edited in two tabs or windows you'll be in a world of hurt. I suggest making your bean #ViewScoped (for CDI, there's a separate extension made by the Seam3 that enables this, if you can't/won't use this extension consider using #ManagedBean instead of #Named).
Also, you might want to declare your instance variables to be private and give ejbFacade a better name (e.g. personalInfoFacade). I also doubt whether immediate is necessary on the commandButton, and since the outputText is obviously a label for the given inputText, you might want to consider using outputLabel and the for attribute.
How can I dynamically change managed bean of "value" attribute? For example, I have h:inputText and, depending on typed-in text, managed bean must be #{studentBean.login} or #{lecturerBean.login}. In a simplified form:
<h:inputText id="loginField" value="#{'nameofbean'.login}" />
I tried to embed another el-expression instead of 'nameofbean':
value="#{{userBean.specifyLogin()}.login}"
but it doesn't worked out.
Polymorphism should rather be done in the model, not in the view.
E.g.
<h:inputText value="#{person.login}" />
with
public interface Person {
public void login();
}
and
public class Student implements Person {
public void login() {
// ...
}
}
and
public class Lecturer implements Person {
public void login() {
// ...
}
}
and finally in the managed bean
private Person person;
public String login() {
if (isStudent) person = new Student(); // Rather use factory.
// ...
if (isLecturer) person = new Lecturer(); // Rather use factory.
// ...
person.login();
// ...
return "home";
}
Otherwise you have to change the view everytime when you add/remove a different type of Person. This is not right.
Another way:
<h:inputText id="loginField1" value="#{bean1.login}" rendered="someCondition1"/>
<h:inputText id="loginField2" value="#{bean2.login}" rendered="someCondition2"/>
I want to learn that if I can define user input parameters at bean class and take these input parameters from a controller function with submit button :
for example input
jsp :
<h:inputSecret value="#{control.userObj.pwrd}"></h:inputSecret>
<h:commandButton type="submit" value="Giris" action="#{control.check}">
</h:commandButton>
"User" bean class :
private String userName; (with getter and setter)
"Control" controller class :
private User userObj;
When using nested bean properties, then you need to prepare it yourself so that JSF can call the setters on it. JSF/EL namely won't prepare them for you.
public class Control {
private User userObj;
#PostConstruct
public void init() {
userObj = new User();
}
// ...
}
This way #{control.userObj.userName} will work in input fields.
See also:
JSF 2.0 Hello World - The Model, Controller and View