i am working with 3.0 M3 . when i declare my managed beans in faces-config.xml, it works perfectly, but when i try the same codes with
annotations #Managed bean #Request Scoped, it says target UN-reachable.
i tried on 2.2 also, but it says same issue again.
I am using glass fish v3
#ManagedBean
#SessionScoped
public class Profile implements Serializable{
private String userId;
private String password;
private int code;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Here is how i call them
<h:form>
<p:panel style="margin-top: 200px;margin-left: 300px;margin-right: 300px;" header="Welcome">
<h:outputText value="Your Code ? "/>
<h:inputText required="true" requiredMessage="Enter user id" value="#{Profile.userId}"/>
<h:outputText value="Password "/>
<h:inputSecret required="true" requiredMessage="Enter password id" value="#Profile.password}"/>
<h:commandButton action="#{Profile.varify}" value="Next"/>
</p:panel>
</h:form>
Profile should be lowercase, and check the syntax on password line
If you don't use the name attribute of the #ManagedBean annotation, you have to refer to the bean with the first letter converted to lower case.
From the #ManagedBean javadoc:
The value of the name() attribute is taken to be the
managed-bean-name. If the value of the name attribute is unspecified
or is the empty String, the managed-bean-name is derived from taking
the unqualified class name portion of the fully qualified class name
and converting the first character to lower case. For example, if the
ManagedBean annotation is on a class with the fully qualified class
name com.foo.Bean, and there is no name attribute on the annotation,
the managed-bean-name is taken to be bean. The fully qualified class
name of the class to which this annotation is attached is taken to be
the managed-bean-class.
Since you are using jsf2
you can do the following - give a name to the bean...
#ManagedBean(name="Profile")
#SessionScoped
public class Profile implements Serializable{
}
Check the import package of #SessionScoped, it must be import javax.faces.bean.SessionScoped;
and also give name to ManageBean #ManagedBean(name="Profile")
Related
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.
Using JSF 2.0 and EL, I am trying to call a method on a POJO which is an attribute of a viewscoped bean. The code is actually very similar to #BalusC's tutorial here. When I call a method that takes no arguments, everything's fine. But when I try to call a method that takes an argument, I get the following exception:
javax.faces.el.MethodNotFoundException: javax.el.MethodNotFoundException:
/user.xhtml at line 42 and column 32 action="#{users.user.removeFriend(friend)}":
Method not found: model.User#67f2b0dd.removeFriend()
Here are some more details:
user.xhtml
<f:metadata>
<f:viewParam name="id" value="#{users.id}" />
<f:event type="preRenderView" listener="#{users.init}" />
</f:metadata>
...
<h:form id="usersForm">
<p:outputPanel>
<p:dataTable id="userTable" value="#{users.user.friendList}" var="friend">
<p:column>
<h:outputText value="#{friend.name}" />
</p:column>
<p:column>
<p:commandButton action="#{users.user.removeFriend(friend)}"
ajax="true"
update="userTable somethingElse" process="#this"
onerror="errorDialog.show();"
icon="ui-icon-delete"
title="delete user">
</p:commandButton>
</p:column>
</p:dataTable>
</p:outputPanel>
<p:commandButton action="#{users.user.removeAllFriends()}" ajax="true"
update="userTable somethingElse"
process="#this"
icon="ui-icon-close"
value="delete all friends?">
</p:commandButton>
</h:form>
I have the following ViewScoped bean:
Users.java
#ManagedBean(name = "users")
#ViewScoped
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private User user;
#ManagedProperty("#{userService}")
private UserService userService; // session scoped
public void init() {
user = userService.getCart(id);
}
public final String getId() {
return id;
}
public final void setId(String id) {
this.id= id;
}
public final User getUser() {
return user;
}
public final void setUser(User user) {
this.user= user;
}
public final void setUserService(UserService userService) {
this.userService = userService;
}
}
The User class - a POJO - has a private List<Friend> friends attribute, with getter and setters and a public method User#removeFriend(Friend f). It has another public method; User#removeAllFriends().
The page renders fine but I get the exception when I click the "Remove" commandButton next to a user in the table.
What's wrong here? Why can I successfully call a parameter-less method but can't pass arguments to another?
Edit: The application is deployed on Tomcat 7.0, if that's any good.
Any help appreciated.
Update: As BalusC and Neo pointed, this is an issue with Tomcat 7.0. I installed WebLogic 12.1 and it all worked fine.
This is a bug in Tomcat. It works when you call the method on the bean directly, but not when you call it on a nested property. I recall this issue as issue 50449 which I have ever reported but was closed as "works for me" (perhaps they did not test it very properly, I didn't find it worth the effort to argue with Tomcat guys again, I haven't had very good experiences with them). In any way, I have re-reported it as issue 52445 with a more solid testcase -I hope.
In the meanwhile, replacing the EL implementation with a different one, from Glassfish for example, should work out. But I can tell you that whatever you're trying to do is not really the proper approach. You've declared a business method on the model (the User entity class) instead of on the controller (the Users managed bean class). This is not right. The model should solely be used to hold the data. The controller should be used to hold the business actions.
I recommend to rewrite your case as follows:
<h:form id="usersForm">
<p:outputPanel>
<p:dataTable id="userTable" value="#{users.user.friends}" var="friend">
<p:column>
<h:outputText value="#{friend.name}" />
</p:column>
<p:column>
<p:commandButton action="#{users.removeFriend(friend)}"
process="#this" update="userTable somethingElse" onerror="errorDialog.show();"
icon="ui-icon-delete" title="delete user" />
</p:column>
</p:dataTable>
</p:outputPanel>
<p:commandButton action="#{users.removeAllFriends}"
process="#this" update="userTable numUsers"
value="delete all friends?" />
</h:form>
and put the business methods in the Users managed bean instead:
public void removeFriend(Friend friend) {
userService.removeFriend(user, friend);
// ...
}
public void removeAllFriends() {
userService.removeAllFriends(user);
// ...
}
Also the UserService being another #ManagedBean is not entirely right. It should actually be an #Stateless EJB, but that's another story. EJBs are not supported on Tomcat anyway without enriching it with for example OpenEJB. Without EJB, it does not necessarily need to be another managed bean. You don't want to expose those services into the view directly.
Ahh.. that explains it # Tomcat.. The way in which you are passing the parameter "#{users.user.removeFriend(friend)}" is EL 2.2. You can overcome that by following the steps here: http://www.mkyong.com/jsf2/how-to-pass-parameters-in-method-expression-jsf-2-0/ OR by using some other way as described here: http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/. Good luck!
If you are using Tomcat you can do the following.
In the xhtml file you do something like this.
#{ItemInformationController.setFindItem(525)}
#{ItemInformationController.findItem}" var="AVar">
In your controller file you can do something like this:
int itemId;
public List<Item> getFindItem() {
return getJpaController().findLevel3Item(levelId);
}
public void setFindItem(int id) {
itemId= id;
}
This works find with Tomcat 6/7...
enter code here
#ManagedBean(name = "customerBean")
#SessionScoped
public class CustomerBean implements Serializable {
/**/
private static final long serialVersionUID = 1L;
CustomerManager customerManager = CustomerManager.getInstance();
private Book book;
private Long id;
private String name, vorname, addresse, ort;
Customer customer = new Customer();
ArrayList<Customer> customerList;
public void findCustomer(String name){
CustomerManager.getInstance().findCustomerByName(name);
System.out.println("Hello" + customer.getName());
}
getters and setters...
public class CustomerManager {
static EntityManagerFactory emf;
static EntityManager em;
static CustomerManager instance;
EntityTransaction entityTransaction = null;
public CustomerManager() {
emf = Persistence.createEntityManagerFactory("customerRegistration");
em = emf.createEntityManager();
}
List<Customer> customerstList = new ArrayList<Customer>();
Book book = new Book();
Set<Book> bookList = new HashSet<Book>();
Customer customer = new Customer();
public void findCustomerByName(String name) {
// Query for a single object.
Query query = em.createQuery("Select c FROM Customer c WHERE c.name = :name");
query.setParameter("name", name);
System.out.println("Hello from Business");
customer = (Customer)query.getSingleResult();
}
<ui:define name="content">
<h:body>
<h:form id="main">
<p:panelGrid columns="2">
<p:outputLabel for="name" value="#{texts.name}" />
<p:inputText id="name" value="#{customerBean.customer.name}" />
<h:commandButton value="Search"
action="#{customerBean.findCustomer()}" />
</p:panelGrid>
</h:form>
</h:body>
</ui:define>
I am trying to do some "custom lightweight" JSF component binding. In my bean (controlling some JSF page) i'm declaring a HahsMap where keys ranging over my h:inputText ids (appearing in the page) map these ids to custom HInputText<T> objects (T in the example given below is Long). Then i am using HInputText<T> objects to hold a subset of corresponding h:inputText attributes : value supposed to be of type T, rendered, required, etc. In this direction fields from the HInputText<T> objects give values to the h:inputText attributes.
My problem is that when using such an h:inputText inside a h:form, JSF validation does not take place : i can type alphanumeric chars in the h:inputText (supposed to hold a Long value) and my form submits without showing any errors. Note that required and rendered attributes are managed correctly (since required is set to true, i have an error when i leave the h:inputText field empty) and that when i try to display back the value of the h:inputText in the page using some h:outputText the alphanumeric chars are displayed.
Is there some trick to make JSF validation work without having to explicitly define a custom Validator for each h:inputText?
HInputText.class:
public class HInputText<T>
{
private String id;
private boolean rendered;
private boolean required;
private T value;
private Class<T> myClass;
// getters and setters for all fields
public HInputText(Class<T> myClass, String id)
{
this.myClass = myClass;
this.id = id;
this.rendered = true;
this.required = true;
}
}
Code snippet from my Managed Bean :
#ManagedBean(name="saisieController")
#SessionScoped
public class SaisieController
{
...
private HashMap<String,HInputText<Long>> htagLongInputTexts;
public HashMap<String, HInputText<Long>> getHtagLongInputTexts()
{
return htagLongInputTexts;
}
public void setHtagLongInputTexts(HashMap<String, HInputText<Long>> hLongInputTexts)
{
this.htagLongInputTexts = hLongInputTexts;
}
public void addHtagLongInputText(HInputText<Long> hLongInputText)
{
getHtagLongInputTexts().put(hLongInputText.getId(), hLongInputText);
}
public HInputText<Long> getHtagLongInputText(String hLongInputTextId)
{
return(getHtagLongInputTexts().get(hLongInputTextId));
}
#PostConstruct
public void init()
{
setHtagLongInputTexts(new HashMap<String, HInputText<Long>>());
addHtagLongInputText(new HInputText<Long>(Long.class, "HIT_LongTestHIT"));
}
public String doNothing()
{
return null;
}
}
and finally a snippet from my jsf page:
<h:form>
<h:inputText
id = "HIT_LongTestHIT"
value = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].value}"
rendered = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].rendered}"
required = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].required}"
/>
<h:message for = "HIT_LongTestHIT" styleClass = "error-text" />
<h:commandButton value = "submit" action = "#{saisieController.doNothing()}" />
<h:outputText value = "#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].value}" />
</h:form>
Is there some trick to make JSF validation work without having to explicitly define a custom Validator for each h:inputText?
No, that's not possible. Due to type erasure the generic type information is not available during runtime. JSF/EL has no idea that T is actually a Long, let alone that there's actually some T. You really need to explicitly specify a converter which is in this particular example the LongConverter with a converter ID of javax.faces.Long.
<h:inputText ... converter="javax.faces.Long">
or, dynamically so you want
<h:inputText ...>
<f:converter converterId="#{saisieController.htagLongInputTexts['HIT_LongTestHIT'].converterId}" />
</h:inputText>
You can find an overview of all available standard JSF converters in the javax.faces.convert package summary. You can find out their converter IDs by navigating to the Constant field values link on the public constant CONVERTER_ID.
I have already one session scoped CDI bean, which keeps currently logged in user data.
Now, from another, request scoped I would like to access to this bean to get some data. I have some operation to do, which is dependent on user login. That's the only information I need.
How to access it?
AccountBean.java:
#Named("accountBean")
#SessionScoped
public class AccountBean implements Serializable {
private static final long serialVersionUID = 16472027766900196L;
#Inject
AccountService accountService;
private String login;
private String password;
// getters and setters ommited
}
Part of login.xhtml:
<h:form>
<h:panelGrid columns="2">
#{msgs.loginPrompt}
<h:inputText id="login" value="#{accountBean.login}" />
#{msgs.passwordPrompt}
<h:inputSecret id="password" value="#{accountBean.password}" />
<h:commandButton value="#{msgs.loginButtonText}"
action="#{accountBean.login}" />
</h:panelGrid>
</h:form>
SearchBean.java:
#Named("searchBean")
#RequestScoped
public class SearchBean {
#Inject AccountBean accountBean;
// some other stuff
}
Just #Inject it.
#Inject
private Bean bean;
Note that this isn't available in the constructor of the receiving bean (it's not possible to inject something in an unconstructed instance, you see). The earliest access point is a #PostConstruct method.
#PostConstruct
public void init() {
bean.doSomething();
}
This is a pattern that I would use over and over again if I get it to work. I have an enum name Log.LogKey that I want to user to pick out instances of. So the facelet has this:
<h:form id="testForm" >
<h:selectManyCheckbox value="#{test.selectedKeys}" >
<f:selectItems value="#{test.allKeys}"
var="lk"
itemLabel="#{lk.display}"
itemValue="#{lk}" />
</h:selectManyCheckbox>
<h:commandButton value="Do It" action="#{test.doNothng}" />
</h:form>
The enum has a getter called getDisplay(). The selectItems attribute calls that correctly because that's the string that gets rendered to the user. And the backing bean has this:
public class Test implements Serializable {
private List<Log.LogKey> selectedKeys = null;
public List<Log.LogKey> getAllKeys() {
return Arrays.asList(Log.LogKey.values());
}
public List<Log.LogKey> getSelectedKeys() { return selectedKeys; }
public void setSelectedKeys(List selected) {
System.out.println("getSelecgedKeus() got " + selected.size());
int i = 0;
for (Object obj : selected) {
System.out.println(i++ + " is " + obj.getClass() + ":" + obj);
}
}
public String doNothng() { return null; }
}
So on the form submit, the array setSelectedKeys(selected) gets called with a List of Strings, not a List of Log.LogKey. The reference to #{lk} in the selectItems tag is converting the object to a string. What would be the right way to do this?
You need to specify a converter. JSF EL is not aware about the generic List type because that's lost during runtime. When you do not explicitly specify a converter, JSF will not convert the submitted String values and plain fill the list with them.
In your particular case, you can make use of the JSF builtin EnumConverter, you just have to super() the enum type in the constructor:
package com.example;
import javax.faces.convert.EnumConverter;
import javax.faces.convert.FacesConverter;
#FacesConverter(value="logKeyConverter")
public class LogKeyConverter extends EnumConverter {
public LogKeyConverter() {
super(Log.LogKey.class);
}
}
To use it, just declare it as follows:
<h:selectManyCheckbox value="#{test.selectedKeys}" converter="logKeyConverter">
...
</h:selectManyCheckbox>
See also:
Use enum in h:selectManyCheckbox