JSF - Set multiple values on #ManagedProperty in a single bean - jsf

I need to set 2 different ManagedProperty on the same bean. So i tried :
#ManagedBean(name="selector")
#RequestScoped
public class Selector {
#ManagedProperty(value="#{param.page}")
#ManagedProperty(value="#{param.profile_page}")
private String page;
private String profile_page;
public String getProfile_page() {
if(profile_page==null || profile_page.trim().isEmpty()) {
this.profile_page="main";
}
return profile_page;
}
public void setProfile_page(String profile_page) { this.profile_page = profile_page; }
public String getPage() {
if(page==null || page.trim().isEmpty()) {
this.page="homepage";
}
return page;
}
public void setPage(String page) { this.page=page; }
}
but unfortunatly i can't write 2 different #ManagedProperty : it says duplicate annotations. How can I fix it?
Another : when i return this value, its a String, and i need to confrontate. This syntax :
<h:panelGroup rendered="#{selector.profile_page.compareTo("main")}">
<ui:include src="/profile/profile_main.xhtml" />
</h:panelGroup>
will work?
Cheers

The annotations have to be declared directly before the class, method or field of interest.
So:
#ManagedProperty(value="#{param.page}")
private String page;
#ManagedProperty(value="#{param.profile_page}")
private String profile_page;

Related

How to populate injected bean in jsf

I have a simple form :
<h:form>
<h:inputText value="#{storyController.story.author}"/>
<h:commandButton action="#{storyController.save}" value="save"/>
</h:form>
and a bean like this :
#Model
public class Story {
private String author;
//getter and setter...
}
and a controller :
#Model
public class StoryController {
private StoryService storyService;
private Story story;
#Inject
public StoryController(StoryService storyService, Story story) {
this.storyService = storyService;
this.story = story;
}
public String save() {
System.out.println(story.getAuthor());
return "index.xhtml";
}
public Story getStory() {
return story;
}
public void setStory(Story story) {
this.story = story;
}
}
Now when I fill the author field and click on save button, the bean is not populated (the bean is injected correctly, it's not null).
If instead I do story = new Story() in constructor, then the bean is correctly populated. I want to avoid doing, this, I think that injecte bean is a better practice right?
I tried to set input value like : #{story.author} but still not populated.
What am I doing wrong?

JSF rendered form not working

I have this problem with JSF rendering. I have this bean containing boolean type value ulogovan.
#Named("sessionBean")
#SessionScoped
public class SessionBean implements Serializable{
private boolean ulogovan;
private Zaposleni ulogovanZaposleni;
public SessionBean() {
ulogovan = false;
ulogovanZaposleni = null;
}
public boolean getUlogovan() {
return ulogovan;
}
public void setUlogovan(boolean ulogovan) {
this.ulogovan = ulogovan;
}
I have to show a form depending on a value of ulogovan. Here is the begining of the form:
<h:form id="form" rendered="#{sessionBean.ulogovan == true}">
Because ulogovan = false; so when you said #{sessionBean.ulogovan == true} that mean false == true which is false. Thus, your form will not be rendered unless you set ulogovan to be true.
If you want your form to be rendered depending on the value of ulogovan, just do it like this:
<h:form id="form" rendered="#{sessionBean.ulogovan}">
You can include #PostConstruct annotation on init() method.
So before rendering the page this method will be called first.
You can set the condition in this you wish
#Named("sessionBean")
#SessionScoped
public class SessionBean implements Serializable{
private boolean ulogovan;
private Zaposleni ulogovanZaposleni;
#PostConstruct
public void init() {
setUlogovan(false);
ulogovanZaposleni = null;
}
public boolean getUlogovan() {
return ulogovan;
}
public void setUlogovan(boolean ulogovan) {
this.ulogovan = ulogovan;
}
This will work definately.

Custom component inside <ui:repeat> doesn't find iterated item during encode

I'm trying to create a custom component for displaying an Entity with a certain form. So I've created my #FacesComponent and he's working but only when he is not inside a loop like <ui:repeat>. When I'm using the following code, my component is displaying null values for price and photo but not for name. Do you have an explaination ?
XHTML code :
<ui:define name="content">
<f:view>
<h:form>
<ui:repeat value="#{dataManagedBean.listNewestCocktails}" var="item" varStatus="status">
<h:outputText value="#{item.price}"/> <!--working very well-->
<t:cocktailVignette idPrefix="newCocktails" name="foo" price="#{item.price}" urlPhoto="#{item.photoURI}"/> <!-- not working the getPrice here -->
</ui:repeat>
<!--<t:cocktailVignette idPrefix="allCocktails" name="OSEF" price="20" urlPhoto="osefdelurl" ></t:cocktailVignette> -->
</h:form>
</f:view>
My component code :
package component;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.ResponseWriter;
#FacesComponent(value = "CocktailVignette")
public class CocktailVignette extends UIComponentBase {
private String idPrefix;
private String name;
private String price;
private String urlPhoto;
public String getIdPrefix() {
return idPrefix;
}
public void setIdPrefix(String idPrefix) {
this.idPrefix = idPrefix;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getUrlPhoto() {
return urlPhoto;
}
public void setUrlPhoto(String urlPhoto) {
this.urlPhoto = urlPhoto;
}
#Override
public String getFamily() {
return "CocktailVignette";
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.write("<div id=\""+idPrefix+name+"\" class=\"cocktail-vignette\">");
writer.write("<h2>"+name+"</h2>");
writer.write("<h3>"+price+"</h3>");
writer.write("</div>");
}
}
Thanks a lot :) I'm trying but nothing is working ...
All of component's attributes which are sensitive to changes in state (e.g. the value being dependent on <ui:repeat var>, at least those which is not known during view build time but during view render time only), must delegate the storage of attribute value to the state helper as available by inherited getStateHelper() method.
Kickoff example:
public String getPrice() {
return (String) getStateHelper().eval("price");
}
public void setPrice(String price) {
getStateHelper().put("price", price);
}
Apply the same for all other attributes and get rid of the instance variable declarations. Important note is that the state helper key ("price" in above example) must be exactly the same as attribute name.
See also:
How to save state when extending UIComponentBase

Using a Enum with a ActionParam

I am using the following piece of code in my JSF 2.0 with RichFaces 4.0. I have a managed bean that has an enum. Now i want to assign the value of the enum via an ActionParam. How can I do this? Here is the code:
<a4j:commandLink id="pendingTransactions"
action="#{tellerBean.getPendingTransactions}" value="Show Pending"
styleClass="button category-btn">
<a4j:actionparam name="first" value=""
assignTo="" />
</a4j:commandLink>
and my managed bean:
#ManagedBean
#SessionScoped
public class TellerBean implements Serializable{
public enum TransactionType {
PENDING,PROCESSED,ALL
}
private static final long serialVersionUID = -321111;
private String recipientID;
private String recipientName;
private String transactionAmount;
private TransactionType transactionType;
public String getRecipientID() {
return recipientID;
}
public void setRecipientID(String recipientID) {
this.recipientID = recipientID;
}
public String getRecipientName() {
return recipientName;
}
public void setRecipientName(String recipientName) {
this.recipientName = recipientName;
}
public String getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(String transactionAmount) {
this.transactionAmount = transactionAmount;
}
public void searchTransactions() {}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
public void getTransactions() {}
}
Now I want to assign the value of the transactionType variable to an Enum value. How can I do this?
I don't know what you want to do with the variable or how you want to display it, so here's a generic example.
First of all, the JSF page must be able to 'iterate' over the enum to discover the possible values. I'm using h:selectOneMenu as an example which is filled using f:selectItems. f:selectItems expects a List<> as input so we need to create a method in the TellerBean:
public List<TransactionType> getTransactionTypes()
{
List<TransactionTypes> tt = new ArrayList<TransactionType>();
for (TransactionType t : TransactionType.values())
{
tt.add(new TransactionType(t, t.toString()))
}
return tt;
}
Then for an example JSF page:
<h:form>
<h:selectOneMenu value="#{tellerBean.transactionType}">
<f:selectItems value="#{tellerBean.transactionTypes}"/>
</h:selectOneMenu>
<h:commandButton value="Submit" action="#{tellerBean.someMethod}"/>
</h:form>
The JSF page should display a drop-down list with the values of the enum. When clicking the button labeled "Submit" it executes someMethod() in TellerBean. Of course this doesn't work because the method doesn't exist, but it's just an example. ;-)

How to Dynamically add a row in a table in JSF?

In my application i need to add a row on a click of a button and this button will be in all the rows. Need help to do this?
Item Class
public class Item {
public Item()
{
}
private String value;
public Item(String value) { this.value = value; }
public void setValue(String value) { this.value = value; }
public String getValue() { return value; }
}
Manage Bean Class
public class MyMB
{
private List<Item> list;
public void addItem() { // JSF action method
list.add(new Item("Default"));
Iterator<Item> iterator = list.iterator();
while(iterator.hasNext())
{
Item item = (Item)iterator.next();
System.out.println(item.getValue());
}
System.out.println();
}
/**
* #return the list
*/
public List<Item> getList() {
if(list==null)
{
loadList();
}
return list;
}
private void loadList() {
list = new ArrayList<Item>();
list.add(new Item("Data"));
}
}
JSF code
<h:form>
<rich:dataTable value="#{myMB.list}" var="item" id="tabel">
<h:column><h:inputText value="#{item.value}" /></h:column>
<h:column><a4j:commandButton value="Add" actionListener="#{myMB.addItem}" reRender="tabel"/></h:column>
All you need to do is basically indeed just adding an empty object to the datamodel behind the value attribute of h:dataTable.
But the same empty row needs to be preserved in the subsequent request as well. If the backing bean is request scoped, then the datamodel get reloaded without the empty row. This all should work when the bean is session scoped.
Further there are several errors in your JSF code. The h:dataTable var attribute is missing and the column content needs to be inside a h:column.
<h:form>
<h:dataTable value="#{bean.list}" var="item">
<h:column><h:inputText value="#{item.value}" /></h:column>
</h:dataTable>
<h:commandButton value="Add" action="#{bean.add}"/>
</h:form>
A session or view scoped bean can look like this:
public class Bean {
private List<Item> list;
public Bean() {
list = new ArrayList<Item>();
}
public void add() {
list.add(new Item());
}
public List<Item> getList() {
return list;
}
}
The Item class should of course have a default no-arg constructor. Normally this is already implicitly available, but if you define your own constructor with arguments, then it is not available anymore. You'll need to explicitly define it, otherwise you cannot do Item item = new Item(); anymore.
public class Item {
private String value;
public Item() {
// Keep default constructor alive.
}
public Item(String value) {
this.value = value;
}
// ...
}
If you prefer to keep the bean in the request scope, then you'll need to maintain the amount of newly added items, so that the bean can preserve the same amount on load.
public class Bean {
private List<Item> list;
private HtmlInputHidden count = new HtmlInputHidden();
public Bean() {
count.setValue(0);
}
public void add() {
list.add(new Item());
}
public List<Item> getList() {
if (list == null) loadList();
return list;
}
public HtmlInputHidden getCount() {
return count;
}
public void setCount(HtmlInputHidden count) {
this.count = count;
}
private void loadList() {
list = new ArrayList<Item>();
// Preserve list with newly added items.
for (int i = 0; i < (Integer) count.getValue(); i++) {
list.add(new Item());
}
}
}
You'll only need to add the following to the <h:form> of the JSF page:
<h:inputHidden binding="#{bean.count}" converter="javax.faces.Integer" />
For more insights about using datatables in any way you may find this article useful: Using Datatables. It also contains a WAR file with lot of examples in both request and session scope.
Take this table as an example:
<h:datatable value="#{myBean.list}" ...>
...
<h:column>
<h:commandButton value="Add a row" action="#{myBean.addRow}"/>
</h:column>
</h:datatable>
The method myBean.addRow will simply add a new element in your list:
public class MyBean {
private List<SomeClass> list;
...
public List<SomeClass> getList() {
return list;
}
public void addRow() {
list.add(new SomeClass());
}
}
When you will click on the button, the method addRow will add a new element in the list. The page will refresh and display the table with a new row.
Edit:
Regarding your post edition, three things:
Point 1: Could you please attach the stacktrace of your error?
Point 2: Your method addRow return a String which is an ID used by JSF for the navigation. As this action does not involve any navigation (i.e. the user stay on the same page), simply return null or "":
public String addRow() {
list.add(new Item("new data"));
return null;
}
Point 3: I suggest that your class Item provide an empty constructor (in addition of your current constructor):
public Item() {
}

Resources