How to get field's class type of back bean with converter in jsf? [duplicate] - jsf-2

Let's suppose I have following structure:
1) Managed Bean:
#ViewScoped
#ManagedBean
public class TestBean {
private Test test;
//getters/setters
}
2) Test class:
public class Test {
private String attribute;
//gets/sets
}
3) XHTML
<p:inputText id="test" value="#{testBean.test.atribute}" />
Now, I know there is a way to find and get component instance:
UIComponent c = view.findComponent(s);
From UIComponent, how do I get the type bound to component?
What I need is to get full qualified class name from what is set as "value" attribute in component. Something like: package.Test.attribute.

UIComponent offers getValueExpression("attributeName")
sample :
UIViewRoot viewRoot = Faces.getViewRoot();
UIComponent component= viewRoot.findComponent("x");
ValueExpression value = component.getValueExpression("value");
Class<?> expectedType = value.getType(Faces.getELContext());
NB:Faces here is from Omnifaces, which is a "Collection of utility methods for the JSF API that are mainly shortcuts for obtaining stuff from the thread local FacesContext. "
excepts from getType() javadoc
public abstract Class getType(ELContext context) Evaluates the
expression relative to the provided context, and returns the most
general type that is acceptable for an object to be passed as the
value parameter in a future call to the setValue(javax.el.ELContext. java.lang.Object) method. This is not always the same as
getValue().getClass(). For example, in the case of an expression that
references an array element, the getType method will return the
element type of the array, which might be a superclass of the type of
the actual element that is currently in the specified array element.
For MethodExpression read this.

Related

java struts2 very strange behaviour while using iterator

public class UserAction{
private UserData user;
//getter, setter
public String Load() {
user = UserDao.getInstance().getItem(getUserContext().getId());
request.getSession().setAttribute("item", user);
return super.Load();
}
}
public class PropertyAction {
private List <PropertyData> propertyList;
//getter, setter
#Override
public String execute() throws Exception {
propertyList=PropertyDao.getInstance().getItems();
return "list";
}
}
jsp:
<s:iterator value="propertyList" var="item">
${item.name}
${item.thema}
${item.desc}
</s:iterator>
I want to show very strange behaviour of Struts2.
I click property link -> then run PropertyAction.execute() and it display above jsp.
I click user link -> then run UserAction.Load()
I click property link -> then run PropertyAction.execute() and error has been shown "UserData has no property thema".
I spy what happened and I notice that I set setAttribute with name "item". So if I use var="item" in my iterator in jsp, it doesn not use value from propertyList but from session !
My question is it is correct behaviour ?
This is defined behavior; whether or not it's "correct" is debatable.
Because you're using JSP EL, the Struts request wrapper is responsible for resolving JSP EL expressions. The normal application scopes are searched first (e.g., application, session, request). If nothing is found, only then will the value stack be queried for matching expressions.
If you accessed item via non-JSP EL means, e.g., the <s:property> tag, only the value stack would be queried, and you'd get the expected behavior.
When you mix ELs results are not always what you'd expect, so you must be aware how the frameworks in question relate to each other.

e4 dependency reinjection order: field vs. method

I was quite surprised to see that there is no deterministic behavior for the order in which objects get reinjected.
public class Test {
#Inject private Boolean testBool;
#Inject
public void checkNewObject(Boolean testBoolNew) {
if (!testBoolNew.equals(this.testBool)) {
System.out.println("Out of sync!");
} else {
System.out.println("In sync!");
}
}
}
And this is how I use the class:
context.set(Boolean.class, new Boolean(true));
Test test = ContextInjectionFactory.make(Test.class, context);
context.set(Boolean.class, new Boolean(false));
So, sometimes I get the output:
In sync!
In sync!
And sometimes I get:
In sync!
Out of sync!
Is this really non deterministic or am I just overseeing something?
The documentation clearly states that the injection order should be:
Constructor injection: the public or protected constructor annotated with #Inject with the greatest number of resolvable arguments is selected
Field injection: values are injected into fields annotated with #Inject and that have a satisfying type
Method injection: values are injected into methods annotated with #Inject and that have satisfying arguments
See: https://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection#Injection_Order
I'm not sure, why this doesn't work as expected in your case.
How is equals() implemented in MyContent?
Is MyContent annotated with #Creatable and or #Singleton?
As a side note: Is this a practical or just an academic problem? Why is it necessary to inject the same instance into a field and into a method on the same target-instance? If you want to have a field variable to cache the value, you can set this from the method.
If you feel this is a bug, please file it here: https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Platform

#Named bean not accessible in jsf

my environment is: Maven 3, JSF 2, Tomcat 7, Java 6. I am trying to use the java #Named annotations for my beans, that I use in JSF. The project is simple, with one TestBean that has one getter and setter for one property called text.
#Named
public class TestBean {
String text = "Hello World"
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
}
In my jsf file when I try:
#{testBean.text}
I get no error but also nothing is shown. What do I have to do to be able to access the bean?
#Named annotation only exposes your bean in EL context, it doesn't give it a scope. This defaults to 'dependent' pseudo-scope. Dependent beans are not managed, they are just inserted at injection points and that's it.
Try explicitly adding scope. Also you can use built-in #Model stereotype, which is simply a combination of #Named and #RequestScoped.

Setter of h:selectOneMenu is not invoked [duplicate]

This question already has answers here:
Conversion Error setting value for 'null Converter' - Why do I need a Converter in JSF?
(2 answers)
Closed 6 years ago.
I just tried to change a value of a select input box. Loading the page runs into my breakpoint for the getter method of the pubcategory property. Good so far. Changing the value, does NOT invoke the setter method. I trigger an Richfaces ajax processing. I confirm, that all JSF phases are walked through (I also see the JPA-SQL select queries, where I would expect an update statement for changing the value - well, can't be, if the setter method is not triggered). This is my selectOneMenu code
<h:selectOneMenu id="pubCategoryId" converter="#{pubCategoryConverter}" value="#{pubController.pubCategory}">
<f:selectItems value="#{listPubCategoryController.pubCategories}" var="category" itemLabel="#{category.name}" itemValue="#{category}" />
<a4j:ajax event="change" execute="#this" />
</h:selectOneMenu>
<h:message for="pubCategoryId" style="color:red" />
My converter is invoked on both times. the getAsString method, when I load the page and the getAsObject when the on-change action is triggered. From this I concluse, the change really goes back to the server. But - again - it never triggers the setter method.
#ManagedBean(name = "pubCategoryConverterController")
#FacesConverter(value = "pubCategoryConverter")
//#Named
public class PubCategoryConverter implements Converter {
#Inject
private PubCategoryRepository pubCategoryRepository;
public PubCategoryConverter() {
}
// from page to backing bean
#Override
public Object getAsObject(FacesContext ctx, UIComponent component,
String value) {
PubCategory pubCat = pubCategoryRepository.getPubCategoryById(new Long(
value));
return pubCat;
}
// from backing bean to page
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object o) {
PubCategory pubCat = ((PubCategory) o);
return pubCat.getId().toString();
}
}
Same story if I annotate the converter with #Named instead of #FacesConverter/#ManagedBean. Any clue or hints anyone?
Using JBoss 7.1.1, Richfaces 4.3.3, JSF 2.0
The converter is called in the "Process Validations" phase of the JSF lifecycle whereas the setter is called later, during the "Update Model Values" phase. Each phase goes through the entire page which means a validation error in any component will prevent all model updates. If you're not seeing validation errors on the page try checking your message tags.
The skipping of lifecycle phases is done by calling FacesContext.renderResponse(). See UIInput.executeValidate() and LifeCycleImpl.execute() for details.
I hooked up the phase listener and printed the event.getFacesContext().getMessageList(). And, there is an error although not printed to the <h:Message for="pubCategoryId"/>. The error is msg j_idt18:pubFormE:pubCategoryId: Validation Error: Value is not valid
package com.foo;
import java.util.List;
import java.util.logging.Logger;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseListener;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
public class PhaseTracker implements PhaseListener {
private static final Logger logger = Logger.getLogger("org.exadel.helper");
public void beforePhase(PhaseEvent e) {
List<FacesMessage> msgs = e.getFacesContext().getMessageList();
for (FacesMessage msg : msgs) {
logger.info("before msg " + msg.getSummary() + " :: " + msg.getDetail());
}
logger.info("BEFORE " + e.getPhaseId());
}
public void afterPhase(PhaseEvent e) {
logger.info("AFTER " + e.getPhaseId());
}
}
The issue is with the equals(Object o) method within of the model object (some call that DTO). As stated in many forums, the values that you compare within this method must not look like e.g. this.id == o.id, because it compares instances not the inner state. Use equals instead this.id.equals(o.id). Once that is fixed the error Value is not valid will go away.
After all, I noticed the following. If you want to use the selectOneMenu with the tag attribute converter instead of <f:converter ../>, e.g. ...
<h:selectOneMenu value="#{pubController.pubCategory}" converter="#{pubCategoryConverterController}">
... you need to annotate your converter also as a #ManagedBean instance in addition to #FacesConverter, e.g.
#ManagedBean(name="pubCategoryConverterController")
#FacesConverter(value = "pubCategoryConverter")
On the other hand, if you want to use <f:converter converterId="pubCategoryConverter"> tag, you need to reference the faces converter name - NOT an instance of a managed bean. Notice, there is no EL #{...} around the converter name. However, in this case, you CANNOT inject a bean into your converter. As a consequence, in your converter bean, you need to instantiate a controller from the application context in order to use EJB services. e.g.
PubCategoryController pubCategoryController = ctx.getApplication().evaluateExpressionGet(ctx, "#{pubCategoryController}", PubCategoryController.class);

To get current Instance of the session scoped bean in Jsf 2.0

i referred to this question and i've a similar problem
JSF - Get the SessionScoped Bean instance
I want to get the current instance of a managed bean in another managed bean. I've a SuperBean which is extended in a base Class - baseBean.
I set the value of a list - itemList in baseBean. The getter setter of the list are in SuperBean and I should use this SuperBean in my BackingBean to get the value of the itemList.
I tried using -
Application app = FacesContext.getCurrentInstance().getApplication();
ValueBinding vb = app.createValueBinding("#{superbean}");
SuperClass superclass = (SuperClass) vb.getValue(FacesContext.getCurrentInstance());
When I try to print superclass.getItems(); - It gives only this - []
And also this -
SuperClass superclass = (SuperClass)FacesContext.getCurrentInstance().
getExternalContext().getSessionMap().get("superbean");
When I try to print with this - It throws exception as my superbean entry is not present in the sessionMap even though the entry is placed in facesConfig and also as #ManagedBean and #sessionscoped
Kindly help me resolve this.
You can inject a managed bean into another if the injected bean has the same or broader scope. Here is an example:
#ManagedBean(name = "oneBean")
#ViewScoped
public class OneBean{
// injections
#ManagedProperty(value = "#{anotherBean}")
private AnotherBean anotherBean;
// don't forget to add getter and setter for anotherBean
...
}

Resources