Checkbox and button interaction in JSF - jsf

I have a checkbox:
<webuijsf:checkbox immediate="true" valueChangeListenerExpression="#{user$recentreports.selectSingleCBEvent}" id="selectCB" binding="#{user$recentreports.selectCB}" toolTip="#{msg.report_select}"/>
whose valueChangeListenerExpression method is:
List<RowKey> rowsToBeRemoved=new ArrayList();
public void selectSingleCBEvent(ValueChangeEvent event) throws Exception {
RowKey rowKey = tableRowGroup.getRowKey();
System.out.println("rowKey" + rowKey);
System.out.println("tableRowGroup.getRowKey().toString()" + tableRowGroup.getRowKey().toString());
rowsToBeRemoved.add(rowKey);
FacesContext.getCurrentInstance( ).renderResponse( );
}
I have a button that must be used for deleting rows that checkbox component is selected:
<webuijsf:button actionExpression="#{user$recentreports.deleteButton_action}" id="deleteButton" text="#{msg.report_delete_selected}"/>
whose backing bean is:
public String deleteButton_action() {
for(RowKey rowToBeRemoved:rowsToBeRemoved){
try {
System.out.println("rowToBeRemoved" + rowToBeRemoved);
GeneratedReport generatedReport = (GeneratedReport) reportList.getObject(rowToBeRemoved);
Query resultQuery = queryGeneration(generatedReport.getId());
List<String> dropTableQueries = resultQuery.getResultList(); // generated the queries to drop r tables
for(int i=0; i<dropTableQueries.size(); i++){
String aDropTableQuery;
aDropTableQuery = dropTableQueries.get(i); // get single drop table query
entityManager.createNativeQuery(aDropTableQuery);
reportList.removeRow(rowToBeRemoved);
reportList.commitChanges();
}
generatedReportJpaController.delete(generatedReport);
reportList.commitChanges();
analyzerResultService.drop(generatedReport.getId().longValue());
} catch (Exception e) {
error("Cannot delete report with row key " + rowToBeRemoved + e);
}
}
return null;
}
output of this form is:
[#|2011-10-17T11:47:14.304+0300|INFO|glassfishv3.0|null|_ThreadID=25;_ThreadName=Thread-1;|rowKeyRowKey[0]|#]
[#|2011-10-17T11:47:14.304+0300|INFO|glassfishv3.0|null|_ThreadID=25;_ThreadName=Thread-1;|tableRowGroup.getRowKey().toString()RowKey[0]|#]
[#|2011-10-17T11:47:14.304+0300|INFO|glassfishv3.0|null|_ThreadID=25;_ThreadName=Thread-1;|rowKeyRowKey[1]|#]
[#|2011-10-17T11:47:14.304+0300|INFO|glassfishv3.0|null|_ThreadID=25;_ThreadName=Thread-1;|tableRowGroup.getRowKey().toString()RowKey[1]|#]
which means my deleteButtonAction is reached but is not performing the actions that I write (getting rowKey from rowsToBeRemoved and deleting them), I don't understand why. Back bean is request scoped does it have any relevance?

My impression is you short-circuit JSF lifecycle by calling FacesContext.getCurrentInstance( ).renderResponse( ) in selectSingleCBEvent and your actionListener is never reached.
ValueChangeListeners for immediate inputs are called in ApplyRequestValues phase. ActionListeners are called later in InvokeApplication phase. By calling renderResponse() you skip the rest of the cycle and proceed directly to RenderResponse phase.

Related

Dynamically populate h:SelectOneListbox

Currently I'm trying to populate the h:selectOneListbox with values from database.
My function to fetch the data findAllCriteria()
public List<String> findAllCriteria() {
try {
List<Criteria> crits = criteriaFacade().findAllByAnmeldename(getCurrentUserName(),
getCriteriaDefinition().getName());
List<String> results = new ArrayList<>();
for (Criteria crit : crits) {
results.add(crit.getId().toString());
}
return results;
} catch (BusinessException e) {
LOG.error("failed to load criteria" + e);
messageFactory().makeAndAdd(e);
return null;
}
}
this function I'm passing to my Converter criteriaToSelectItems(meldungListController.findAllCriteria())
public static List<SelectItem> criteriaToSelectItems(List<String> elements) {
List<SelectItem> items = new ArrayList<SelectItem>(elements.size());
for (String element : elements) {
items.add(new SelectItem(element, element));
}
return items;
}
as defined here:
<function>
<function-name>criteriaToSelectItems</function-name>
<function-class>de.db.udg.diagnose.udgdiag.webui.app.facelets.functions.SelectItemsFunctions</function-class>
<function-signature>java.util.List criteriaToSelectItems(java.util.List)</function-signature>
The critial part is:
<h:selectOneListbox id="critList" size="1"
value="#{meldungListController.findCriteriaById(identifier)}">
<f:selectItems
value="#{d:criteriaToSelectItems(meldungListController.findAllCriteria())}" />
</h:selectOneListbox>
I don't understand how to retrieve the Item(String) from the selected Item and how to further process it.
public Criteria findCriteriaById(String identifier) {
if (identifier.isEmpty()) {
return querySpec.getCriteria();
}
Long id = Long.valueOf(identifier);
Criteria criteria;
try {
criteria = criteriaFacade().findById(id);
} catch (BusinessException e) {
LOG.error("failed to load criteria" + e);
messageFactory().makeAndAdd(e);
return null;
}
return criteria;
}
Both functions are nested inside of #Component("meldungListController")
)
I've read through this article on SO but this is kind of limited to JSF 2.x
Upgrading my JSF Version from 1.2 to 2.x is no option.
Question
How to dynamically populate selectOneListbox in JSF 1.2 and find the value of the selected index.
In-Depth:
Listing all selectItems works, see image, but:
javax.el.PropertyNotFoundException: /pages/meldung/meldungList.xhtml #341,72 value="#{meldungListController.findCriteriaById(identifier)}": The class 'de.db.udg.diagnose.udgdiag.webui.meldung.MeldungListController' does not have the property 'findCriteriaById'.
I hope someone remembers the good old days with JSF 1.2 and can help me.

My sessionscoped bean does not have values stored on every refresh

I have a SessionScoped Bean which consists of a list and a flag. The list populates a datatable in the xhtml view.
On first load, the list is populated. Every other load should not repopulate the list but it does despite the check. This behaviour also holds for postbacks on commandLinks clicks.
#ManagedBean(name = "customerSegmentInfo")
#SessionScoped
public class CustomerSegmentInfo extends BasePage implements Serializable {
private boolean isNBACalled = false;
private List<NextBestActionDTO> nextBestActionList = null;
public List<NextBestActionDTO> getNextBestActionList() {
log.debug("----- nbaCalled: " + isNBACalled);
if(nextBestActionList == null && !isNBACalled){
log.debug("-------- getNextBestAction");
try {
nextBestActionList = this.getNbaService().getNextBestAction(this.getCustomerInfo().getCountryCode(), this.getCustomerInfo().getCustomerNo());
log.debug("---- " + nextBestActionList.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
log.debug("------ error calling nba service bean " + e);
}
isNBACalled = true;
log.debug("----- nbaCalled: " + isNBACalled);
}
return nextBestActionList;
}
public void setNextBestActionList(List<NextBestActionDTO> nextBestActionList) {
this.nextBestActionList = nextBestActionList;
}
}
As the list is not null from last page load and flag also set to true, the call getNextBestAction shouldnt be made, but in logs the flag is false and apparently the list is null too.
the behaviour is irregular
On certain loads it behaves as expected on others not.
I Tried setting the javax.faces.STATE_SAVING_METHOD context parameter in the web.xml to both server and client, nothing changed.
Thank you in advance

How to specify command attribute in h:inputText?

I have a function that I derclare beans in my manager and I want to return the value in inputText but when I put the name of my function in the value attribute of inputText tag like this:
<p: inputText value = "#{ticketBean.getLastIndexTache} "/>
this error appear:
Etat HTTP 500 - /pages/test.xhtml #13,106 value="#{ticketBean.getLastIndexTache}": Property 'getLastIndexTache' not found on type com.bean.TicketBean
here is the java code
#ManagedBean(name="ticketBean")
public class TicketBean {
public int getLastIndexTache() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
int index = 0;
try {
session.beginTransaction();
String sql = "select MAX(t.IDTICKET) from ticket t ";
Query query = session.createSQLQuery(sql);
if( query.uniqueResult()==null){
index=0;
}else{
index=(int) query.uniqueResult();
index=index+1;
}
} catch (HibernateException e) {
// TODO: handle exception
session.getTransaction().rollback();
e.printStackTrace();
}
return index;
}
}
You should use the bean property in value like
<p:inputText value="#{ticketBean.lastIndexTache}"/>
as JSF by itself adds "get" to the property name. Currently it will look for the method getGetLastIndexTache().
Besides its very bad practice to have logic in any getter as they are called multiple times by JSF. Instead you should make an property like
private Integer lastIndexTache; // +getter/setter
and set the value in a #PostConstruct method:
#PostConstruct
public void init() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
// etc....
lastIndexTache = index;
}
The getter would then simply be
public Integer getLastIndexTache() {
return lastIndexTache;
}
and don't forget a setter:
public void setLastIndexTache(Integer newValue) {
lastIndexTache = newValue;
}
Also you should probably put a scope on the bean (for example #ViewScoped).

Method loops after return statement

I have this JSF backing bean method:
public void filterProductsByCategory()
{
filtered = true;
products = controller.obtainProductListByCategory(selectedDesiredCategory);
showMessage("Filtered by selected category");
}
Which calls the obtainProductListByCategory method. This returns a list of products. When it is time to refresh the JSF page (it access the getters for the variables it needs), it enters the getter here:
public List<Product> getProducts()
{
if(filtered)
{
filtered = false;
return products;
}
products = controller.obtainProductList();
return products;
}
The obtainProductList retrieves all the products in the database. My application is a webmarket and what I'm trying to do is to first: get all the products displayed (which is working fine), then: sort by category (there's the problem). For some reason even after the last method enters the if statement and returns, it goes back inside, with the variable filtered false and proceeds with the method.
I found out through debugging that this code seems to execute everytime too (Located in Method.java):
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(1);
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
Curious enough, the above loop I mentioned is repeated for as many products exist in my List the first time I retrieve all the objects (all the objects in my database). In the end the web page gets all the products back again, even when I tried to filter the results in my datatable What is going on here?

how to get jsf clientid of a component in datatable?

i am trying to get the client id of a component in a datatable. the problem is that jsf puts row index before the component id automatically, i.e.
<a id="mappedidentifier_table:1:mappedidentifier_Update" href="#">Update</a>
for a link in the second row (index=1).
i am using the following methods to get the clientId
public static String findClientId(String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot view = context.getViewRoot();
if (view == null) {
throw new IllegalStateException("view == null");
}
UIComponent component = findComponent(view, id);
if (component == null) {
throw new IllegalStateException("no component has id='" + id + "'");
}
return component.getClientId(context);
}
private static UIComponent findComponent(UIComponent component, String id) {
if (id.equals(component.getId())) {
return component;
}
Iterator<UIComponent> kids = component.getFacetsAndChildren();
while (kids.hasNext()) {
UIComponent kid = kids.next();
UIComponent found = findComponent(kid, id);
if (found != null) {
return found;
}
}
return null;
}
however this returns
mappedidentifier_table:mappedidentifier_Update,
instead of
mappedidentifier_table:1:mappedidentifier_Update,
therefore it does not match any element cause the row index in id is missing.
i've read http://illegalargumentexception.blogspot.com/2009/05/jsf-using-component-ids-in-data-table.html
however i intend to have a simpler implementation, rather than TLD function or facelets like the author did.
does anyone have any thoughts ?
thanks,
dzh
however this returns mappedidentifier_table:mappedidentifier_Update instead of mappedidentifier_table:1:mappedidentifier_Update
This will happen if you resolve the clientId outside the context of a row. The row context is set up at each stage of the lifecycle by the UIData control.
It might also happen if you're using immediate evaluation instead of deferred evaluation in your EL expressions - ${} instead of #{}.
As an aside, and as noted in the article, that lookup algorithm will only work if the component identifier is unique to the view; the spec says it need only be unique to the NamingContainer; this need not be a problem if you are careful about using unique component IDs on your page.

Resources