Cannot access inner class in bean - jsf-2

I'm using JSF 2.0. I have a managed bean which I can access through my xhtml page. Inside the bean I declared an inner class. I can access ArrayList<String> of managed bean but not ArrayList<InnerClass> and I get the error that the InnerClass does not have a readable property. Anyone know what's wrong?

That can happen if the inner class is not public. It will then be invisible to other classes outside the package (like as JSF/EL itself!). Make sure that the inner class is public whenever you need to access it by JSF/EL.
public class Bean {
public class InnerClass {
// ...
}
}
Otherwise it will be interpreted as String and you'll get confusing exceptions like
javax.el.ELException: /test.xhtml: Property 'someProperty' not readable on type java.lang.String
when you want to access #{innerClass.someProperty}.

Related

Inject ArrayList using RequiredArgsConstructor

I tried to inject List into constructor through lombok RequiredArgsConstructor
#Slf4j
#Component
#RequiredArgsConstructor (onConstructor = #_(#Inject))
public class ClassA {
#NonNull private List<GoodSkill> skills;
......
}
However then have errors:
[tomcat:launchProperties]
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'ClassA' defined in URL
[jar:file:/XXXXX/ClassA.class]: Unsatisfied dependency expressed
through constructor parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type java.util.List<\GoodSkill>: expected at least 1
bean which qualifies as autowire candidate. Dependency annotations: {}
It seems there is NO bean of for "List<\GoodSkill>"? I guess there's some special rule when injecting List or other Collections? And as for GoodSkill class, I guess I also should add annotation like #Component?
========
edit:
More weird thing is, I re-build package and now it's no longer complaining find no bean for List<\GoodSkill>, but no bean for GoodSkill. I'm very confused.
Injecting is possible only for managed beans. So, for a list you should have somewhere something like:
#Component
public class GoodSkillList extends ArrayList<GoodSkill>{}
for container to find.
Perhaps you have? If you have many of such beans container/Spring might not be able to decide which to use. In that case you can delimit the possible alternatives many ways for example you could set ClassA to accept only:
#NonNull private GoodSkillList skills;
or alternatively you can research howto inject/autowire by name.

FacesContext.getCurrentInstance().getExternalContext().invalidateSession() calls posconstruct twice

I have managed bean by name studentManagedBean. In that bean I have used post construct to intialize studentsList. In another managed bean testbean I was using
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
and redirecting to page students.xhtml where I used to display students.
My question is when I used the FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); and redirected to student.xtml page, init method(post construct) used to call two times. When I commented the above line, init method(post construct) now calls only one time.
can any one tell me what is this invalidate session will exactly do.
#ManagedBean(name = "studentManagedBean" )
#SessionScoped
public class StudentManagedBean implements Serializable {
private List<SBean> stud;
#PostConstruct
private void init(){
this.stud=dao.getAllStudInfo();
}
#ManagedBean(name = "testBean" )
#SessionScoped
public class TestBean implements Serializable {
public String navigate(String name){
if(name.equals("Add student")){
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "student";
}
Apparently, the session scoped bean StudentManagedBean is also referenced in the current view. When the view get built/restored, it may create the bean if it's referenced during view build time. But if you're invalidating the session thereafter, the session scoped bean get destroyed (obviously, since it's stored in the session scope) and will be re-created again when the target view still references it during rendering of the view.
This must make completely sense. If you don't want that the bean is created before you invalidate the session, simply don't reference it anywhere in the current view, either directly in the view, or indirectly as a managed property or a programmatic EL evaluation of another bean which is directly referenced in the current view.
If you can't immediately figure out where it's been referenced, just put a debug breakpoint in the bean's constructor and explore the call stack for the who/what/why.

Use ManagedBean in FacesConverter

I want to use ManagedBean in my Converter. The ManagedBean is responsible for getting data from database. In Converter I want to convert string into object which must be get from database.
This is my Converter
#FacesConverter(forClass=Gallery.class, value="galleryConverter")
public class GalleryConverter implements Converter {
// of course this one is null
#ManagedProperty(value="#{galleryContainer}")
private GalleryContainer galleryContainer;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String galleryId) {
return galleryContainer.findGallery(galleryId);
...
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object gallery) {
...
}
}
I know that galleryContainer will be null and if I want to inject ManagedBean into Converter I can mark it as ManagedBean too. The problem is that I want to do it in beautiful way, I don't want to look for some 'strange solution'. Maybe the problem is in my application? Maybe there is some other good solution to create object which must get data from database and used in converter? I want also to mention that I will prefer to use DependencyInjection instead of creating new object using new statement (it is easier to test and maintain). Any suggestions?
Instead of using #FacesConverter you should use #ManagedBean, because currently faces converter isn't a valid injection target. Nonetheless, you can choose your converter to be a managed bean, thus refer to it in your view as converter="#{yourConverter}" (by managed bean name) instead of converter="yourConverter" (by converter id).
Basic usage example:
#ManagedBean
#RequestScoped
public class YourConverter implements Converter {
#ManagedProperty...
...
//implementation of converter methods
}
Of course, reading BalusC's invaluable Communication in JSF 2.0 will shed some light on this question as well.
It is also worth mentioning that the scope of your converter bean may be changed to, for example, application or session, if it is not supposed to hold any state.

Setting ManagedBean values in another ManagedBean's method

If I am navigating from page one to page two, When I click on Page one's submit button, control goes to the managed bean written corresponding to page one, I want to fetch some result from database and show them to page two, If I set the Database values into the Managed bean corresponding to page two in the first Managed Bean's action method, then will I be able to get those on page two.
Please suggest if my approach is right?
You can inject let's say bean named Bean1 into Bean2 this way
#ManagedBean
#RequestScoped
public Bean2 {
#ManagedProperty(value="#{bean1}")//this is EL name of your bean
private Bean1 injectedBean;
public void setBean1(Bean1 value) {
injectedBean = value; //provide setter for it
}
#PostConstruct
private void init() {
List<YourData> list = injectedBean.getDBData(); //now you can fetch your list
}
Note that you have to provide setter for injection and scope of the injected bean should be always same or higher then the your beans scope (in this case Bean1 has to be at least RequestScope)
P.S. Also you could have some kind of DAO bean which could do all the database database operations for you (it can be EJB bean or even JSF Managed Bean) and then inject it to every ManagedBean which will require cooperation with your DB.

Adding business logic to a domain class using a getter style method name

I'm attempting to add a method to a grails domain class, e.g.
class Item {
String name
String getReversedName() {
name.reverse()
}
}
When I attempt to load the application using grails console I get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory':Invocation of init method failed; nested exception is org.hibernate.PropertyNotFoundException: Could not find a setter for property reversedName in class Item
... 18 more
It looks like Hibernate is interpreting getReversedName() as a getter for a property, however in this case it is a derived field and hence should not be persisted. Obviously in my actual code the business logic I'm exposing is more complex but it isn't relevant to this question. I want to be able to call item.reversedName in my code/gsps.
How can I provide property (getter) access to a method in a Grails domain class without Grails attempting to map it with Hibernate?
I believe you have two choices:
1) Use def
def getReversedName() {
name.reverse()
}
2) Add a transients declaration to the top of your domain object:
static transients = [ 'reversedName' ]
[edit] (I'd go with #1) (I'd go with #2) ;-)

Resources