jsf and controller, bean - java

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

Related

get variables from jsf query sql db display results on another jsf page [duplicate]

I have started learning JSF, but sadly most tutorials out there present only a log in or a register section.
Can you point me to some more in depth examples? One thing I'm interested in is a page presenting a list of products. I'm on page home and I press on page products so that I can see the latest products added. And every time I visit the page, the product list will be created from the latest entries in the database. How can I handle this?
One way to solve this would be to create a session scoped managed bean in which I would place different entities updated through other managed beans. I found this kind of approach in some tutorials, but it seems quite difficult and clumsy.
Which would be the best approach to solve a thing like this? What is the correct usage of session scope in two-page master-detail user interface?
What is the correct usage of session scope
Use it for session scoped data only, nothing else. For example, the logged-in user, its settings, the chosen language, etcetera.
See also:
How to choose the right bean scope?
And every time I visit the page, the product list will be created from the latest entries in the database. How can I handle this?
Typically you use the request or view scope for it. Loading of the list should happen in a #PostConstruct method. If the page doesn't contain any <h:form>, then the request scope is fine. A view scoped bean would behave like a request scoped when there's no <h:form> anyway.
All "view product" and "edit product" links/buttons which just retrieve information (i.e. idempotent) whould be just plain GET <h:link> / <h:button> wherein you pass the entity identifier as a request parameter by <f:param>.
All "delete product" and "save product" links/buttons which will manipulate information (i.e. non-idempotent) should perform POST by <h:commandLink>/<h:commandButton> (you don't want them to be bookmarkable/searchbot-indexable!). This in turn requires a <h:form>. In order to preserve the data for validations and ajax requests (so that you don't need to reload/preinitialize the entity on every request), the bean should preferably be view scoped.
Note that you should basically have a separate bean for each view and also note that those beans doesn't necessarily need to reference each other.
So, given this "product" entity:
#Entity
public class Product {
#Id
private Long id;
private String name;
private String description;
// ...
}
And this "product service" EJB:
#Stateless
public class ProductService {
#PersistenceContext
private EntityManager em;
public Product find(Long id) {
return em.find(Product.class, id);
}
public List<Product> list() {
return em.createQuery("SELECT p FROM Product p", Product.class).getResultList();
}
public void create(Product product) {
em.persist(product);
}
public void update(Product product) {
em.merge(product);
}
public void delete(Product product) {
em.remove(em.contains(product) ? product : em.merge(product));
}
// ...
}
You can have this "view products" on /products.xhtml:
<h:dataTable value="#{viewProducts.products}" var="product">
<h:column>#{product.id}</h:column>
<h:column>#{product.name}</h:column>
<h:column>#{product.description}</h:column>
<h:column>
<h:link value="Edit" outcome="/products/edit">
<f:param name="id" value="#{product.id}" />
</h:link>
</h:column>
</h:dataTable>
#Named
#RequestScoped
public class ViewProducts {
private List<Product> products; // +getter
#EJB
private ProductService productService;
#PostConstruct
public void init() {
products = productService.list();
}
// ...
}
And you can have this "edit product" on /products/edit.xhtml:
<f:metadata>
<f:viewParam name="id" value="#{editProduct.product}"
converter="#{productConverter}" converterMessage="Unknown product, please use a link from within the system."
required="true" requiredMessage="Bad request, please use a link from within the system."
/>
</f:metadata>
<h:messages />
<h:form rendered="#{not empty editProduct.product}>
<h:inputText value="#{editProduct.product.name}" />
<h:inputTextarea value="#{editProduct.product.description}" />
...
<h:commandButton value="save" action="#{editProduct.save}" />
</h:form>
#Named
#ViewScoped
public class EditProduct {
private Product product; // +getter +setter
#EJB
private ProductService productService;
public String save() {
productService.update(product);
return "/products?faces-redirect=true";
}
// ...
}
And this converter for <f:viewParam> of "edit product":
#Named
#RequestScoped
public class ProductConverter implements Converter {
#EJB
private ProductService productService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value == null || value.isEmpty()) {
return null;
}
try {
Long id = Long.valueOf(value);
return productService.find(id);
} catch (NumberFormatException e) {
throw new ConverterException("The value is not a valid Product ID: " + value, e);
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
if (value instanceof Product) {
Long id = ((Product) value).getId();
return (id != null) ? String.valueOf(id) : null;
} else {
throw new ConverterException("The value is not a valid Product instance: " + value);
}
}
}
You can even use a generic converter, this is explained in Implement converters for entities with Java Generics.
See also:
How to navigate in JSF? How to make URL reflect current page (and not previous one)
JSF Controller, Service and DAO
JSF Service Layer
How to inject #EJB, #PersistenceContext, #Inject, #Autowired, etc in #FacesConverter?
Communication in JSF 2.0 - Contains several examples/hints
As a small improvement to what BalusC recommended, sometimes you can remove the required / requiredMessage part from the <f:viewParam> of your "details" screen and instead use the conditional rendering of the editing form (as BalusC did) with a reverse condition for recommending a specific link for the "list/master" screen or, even use a viewAction that would test the param and force a redirect to that list.

JSF: Binding two values from the same form field

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).

jsf : passing a selected hyperlink as a query argument

I have a mySql table of PROJECTS, which I am displaying as a list in the index.xhtml. The projectid column contains hyperlinks. When they're clicked I would like the specific projectid row selected to be passed as the query argument into another jsf file (ListProjects.xhtml) which displays all the project values referring to the projectid selected in the index.xhtml. The index.xhtml page seems to pass the values correctly (when hovering over the selection the url displays the right id value). When actually clicking the selction I get a blank page in the resulting ListPprojects.xhtml:
I'm not sure if it's my choice of tags on index.xhtml where should be replaced by another tag like CommandLink which maps to a bean action.
Alternatively, is tag in the result page (ListProject.xhtml) the right tag to use to retrieve the projectid value as the query argument?
Also if the projectid is an int, should this first be converted to String by using parseInt or other method?
Is the problem in one of the session beans where projectid is resulting in a null value which causes the result page to render blank records? Any advice is greatly appreciated. Thanks in advance!
The named query in the entity bean (projects.java) is:
#NamedQuery(name = "Projects.findByProjectid", query = "SELECT p FROM Projects p WHERE p.projectid = :projectid")
In the index.xhtml I use the following tag to display the hyperlink:
<h:link value="#{item.projectid}" outcome="ListProject">
<f:param name="projectid" value="#{item.projectid}"/>
</h:link>
The ListProjects.xhtml is the page where I would like to display the project details based on the projectid selected in the index.xhtml (and here's where I start getting confused):
<h:column>
<f:facet name="header">
<h:outputText value="Countryid"/>
</f:facet>
<h:commandLink action="#{selProjectMgtBean.selProjectList}" value="#{item.projectid}"/>
</h:column>
My session bean:
#Stateless
public class ProjectSelectedBean implements ProjectSelectedBeanLocal {
#PersistenceContext(unitName = "QueryTrialNoMavenPU")
private EntityManager em;
#Override
public List<Projects> getSelectedProjects(String projectid) {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
projectid=request.getParameter(projectid);
return em.createNamedQuery("Projects.findByProjectid", Projects.class).setParameter ("projectid", projectid).getResultList();
}
}
Finally the calls the methods for rendering the selection:
package com.manaar.beans;
imports....
#Named(value = "selProjectMgtBean")
#RequestScoped
public class SelProjectMgtBean {
#ManagedProperty(value="#{item.projectid}")
private String projectid;
private List<Projects> selProjectList;
#EJB
private ProjectSelectedBeanLocal projectSelectedBeanLocal;
#PostConstruct
public void init() {
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance ().getExternalContext().getRequest();
projectid=request.getParameter("projectid");
selProjectList = projectSelectedBeanLocal.getSelectedProjects();
}
public List<Projects> getSelProjectList() {
return selProjectList;
}
public void setSelProjectList(List<Projects> selProjectList) {
this.selProjectList = selProjectList;
}
}
you didn't set :projectId in query:
you can change code as follow:
public List<Projects> getSelectedProjects(String projectId) {
return em.createNamedQuery("Projects.findByProjectid", Projects.class).setParameter("projectId" , projectId).getResultList();
}
Regarding one of your questions:
Use h:link for pure navigational purposes (with the outcome parameter) and h:commandLink to invoke an action directly (with the action parameter). The called method in this case should return a String telling JSF where to navigate next.

When/where do entities get created on a Java EE web application?

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.

Partially submitting a form for the purpose of "sequentially" asking for input

I have a JSF page where users can enter their car into my database. The form has three input fields:
Manufacturer
Model
Registration
I am using PrimeFaces 3.0.M2 and both the Manufacturer and Model field are autocomplete input fields:
<p:autoComplete id="manufacturer"
minQueryLength="3"
completeMethod="#{carController.completeManufacturer}"
forceSelection="true"
value="#{carController.manufacturer}" />
The field for the model looks the same, with slightly different values obviously.
The managed bean looks as follows (slightly abbreviated):
private String manufacturer;
private String model;
private String registration;
public List<String> completeManufacturer(String query) {
List<String> ms = new ArrayList<String>();
for (Manufacturer m : manufacturerFacade.findAllByName(query)) {
ms.add(m.getLongName());
}
return ms;
}
public List<String> completeModel(String query) {
List<String> ms = new ArrayList<String>();
for (Model m :
modelFacade.findAllByManufacturer(manufacturerFacade.findByName(manufacturer))) {
ms.add(m.getShortName());
}
return ms;
}
The problem lies in completing the model field. I need this field to only display autocompletion results based on the selected manufacturer, but the manufacturer String in the managed bean does not get populated until the entire form is submitted, so I cannot look the models up that are associated with the selected manufacturer.
How would I go about submitting only the manufacturer field, without submitting the entire form, so I can look the models of the selected manufacturer up?
Thanks!
Just add a selectListener, like so:
<p:autoComplete id="manufacturer"
minQueryLength="3"
completeMethod="#{carController.completeManufacturer}"
forceSelection="true"
selectListener="#{carController.manufacturerSelected}"
value="#{carController.manufacturer}" />
and then in the controller:
public void manufacturerSelected(SelectEvent vce) {
String nameOfSelected = vce.getObject().toString();
// whatever logic comes to your mind
}
You could add an extra ajax handler to the manafucturer input field and then handle the onchange event. In the server-side handler, simply remember the new value in your backing bean.
If you then put your backing bean in the view scope, the ajax requests originating from the model input field will get the same instance and you have direct access to the manufacturer field that you previously remembered.

Categories

Resources