JSF 2.0 + Primefaces richtext editor - dependency-injection

<p:editor value="#{editorBean.value}" widgetVar="editor" width="686"
height="390" language="en" align="center">
</p:editor>
Following is my rich-text editor bean picked up from primefaces
#ManagedBean(name = "editorBean")
#SessionScoped
public class EditorBean {
private static final String MANAGED_BEAN_NAME = "editorBean";
private String value;
public static EditorBean getCurrentInstance() {
return (EditorBean) FacesContext.getCurrentInstance()
.getExternalContext().getRequestMap().get(MANAGED_BEAN_NAME);
}
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Apart from this I have another bean say A. I have a method inside A that populates a HTML table. What I want is when the user opens the editor, it should be pre-populated with that HTML table data and of course the changes should get reflected into (String: value). Therefore, you can say that I am trying to tie up both the values together. I think it needs to be done with DI but somehow its not working. If someone can guide or quote an example, it would be really helpful.

One way to do it is rewrite your getValue() method to pick up the value from bean A.
And yes, the reference to your A bean should come from DI:
//injecting a reference to A
#ManagedPropery(value="#{A}") //or whatever is the name of your bean
private A beanA;
public void setBeanA(A beanA) {
this.beanA = beanA;
}
Or, with CDI, just:
#Inject private A beanA
Finally, your getValue method
public String getValue() {
return beanA.getValue()
}

Related

How to achieve multiple #managedBean value in JSF [duplicate]

I searched similar questions but I'm a bit confused. I have a login page, so LoginBean also which is;
#ManagedBean(name = "loginBean")
#SessionScoped
public class LoginBean implements Serializable {
private String password="";
private String image="";
#ManagedProperty(value = "#{loginBeanIdentityNr}")
private String identityNr="";
...
after success, navigates to orderlist page, so I have also OrderBean.
#ManagedBean(name = "OrderBean")
#SessionScoped
public class OrderBean {
List<Ordery> sdList;
public List<Order> getSdList() {
try {
String identityNr ="";
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
LoginBean lBean = (LoginBean) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, "loginBean");
identityNr =lBean.getIdentityNr();
sdList = DatabaseUtil.getOrderByIdentityNr(identityNr);
...
}
I don't need the whole LoginBean, just ManagedProperty "loginBeanIdentityNr". But this code below doesn't work (of course);
identityNr = (String) FacesContext.getCurrentInstance()
.getApplication().getELResolver()
.getValue(elContext, null, "loginBeanIdentityNr");
this time it returns null to me.
I think if I need whole bean property, I can inject these beans, right? So, do you have any suggestions for this approach? can<f:attribute> be used?
The #ManagedProperty declares the location where JSF should set the property, not where JSF should "export" the property. You need to just inject the LoginBean as property of OrderBean.
public class OrderBean {
#ManagedProperty(value="#{loginBean}")
private LoginBean loginBean; // +setter
// ...
}
This way you can access it in the OrderBean by just
loginBean.getIdentityNr();
Alternatively, if you make your OrderBean request or view scoped, then you can also set only the identityNr property.
public class OrderBean {
#ManagedProperty(value="#{loginBean.identityNr}")
private String identityNr; // +setter
// ...
}
Unrelated to the concrete problem: initializing String properties with an empty string is a poor practice.

ComboBox and original value as an array

I have a legacy MongoDB database (collection) where there is single value stored as an array List . But its only a one value that must be, in UI selected with ComboBox. So I have a model bean
class Project {
List<Company> companies;
}
And I would like to bind it and edit with VAADIN ComboBox. Initialy I thought I can use some customer converter for ComboBox but can't get it to work. Combo should edit the first value in the List (Company bean) and store back into companies field as an array to remain compatible. Is it event possible to do it and if so can you give me some hint how to accomplish this?
EDIT: Enhanced explanation
MongoDB model:
class Project {
List<Company> companies;
}
Vaadin UI:
ComboBox companies;
... 'companies' ComboBox is attached to BeanItemContainer which is List ... selection is therefore the only one Company bean, but should be stored, for compatibility reasons, as List with only one item. So basicly ComboBox should be able to read existing List value as single Company, allow selection and store it as List with this one selecten Company.
After the last question update the answer below may not be correct. Waiting for OP to provide details so the answer can be corrected.
You can use a sort of a delegation approach using a ProjectDelegator wrapper. This will allow you to bind the form to the Project name (using the project field) as well as the Company name (using the getCompany() getter)
1. The UI class
#PreserveOnRefresh
#SpringUI
public class MyVaadinUI extends UI {
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
// add the form to the UI
layout.addComponent(new MyForm(new ProjectDelegator(new Project("myProject", new Company("myCompany")))));
}
}
2. The form
// "wrapping" the form in a custom component. not really needed but a nice touch
public class MyForm extends CustomComponent {
public MyForm(ProjectDelegator projectDelegator) {
FormLayout layout = new FormLayout();
// use a binder to create fields and bind the members using reflection
BeanFieldGroup<ProjectDelegator> binder = new BeanFieldGroup<>(ProjectDelegator.class);
// bind the project name using the "project" field
layout.addComponent(binder.buildAndBind("Project", "project.name"));
// bind the company name using the "getCompany" method
layout.addComponent(binder.buildAndBind("Company", "company.name"));
// add a "save" button
layout.addComponent(new Button("Save", new Button.ClickListener() {
#Override
public void buttonClick(Button.ClickEvent clickEvent) {
try {
// commit changes
binder.commit();
} catch (FieldGroup.CommitException e) {
// didn't expect this! what gives?!
System.out.println("Could not save data: [" + e.getMessage() + "]");
}
}
}));
// set the delegator as the binder data source
binder.setItemDataSource(projectDelegator);
setCompositionRoot(layout);
}
}
3. The "delegator"
// delegator class to adapt from/to list with only 1 item
public class ProjectDelegator {
// nice constant to express the intent as clearly as possible
private static final int MY_ONLY_COMPANY = 0;
// our delegate
private Project project;
public ProjectDelegator(Project project) {
this.project = project;
}
// BeanFieldGroup will use this by reflection to bind the "company.name" field
public Company getCompany() {
// delegate the accessing to the origina product
return project.getCompanies().get(MY_ONLY_COMPANY);
}
// accessor; can if not required at a later time
public Project getProject() {
return project;
}
}
4. The legacy model classes
// our problem class
public class Project {
private String name;
private List<Company> companies = new ArrayList<>();
public Project(String name, Company company) {
this.name = name;
companies.add(company);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Company> getCompanies() {
return companies;
}
public void setCompanies(List<Company> companies) {
this.companies = companies;
}
}
// the "indirect" problem :)
public class Company {
private String name;
public Company(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("Setting actual company name to [" + name + "]");
this.name = name;
}
}
5. Resulting UI
6. Pressing the save button
Setting actual company name to [myNewCompany]

JSF Navigation outcome constants

I wonder if i can replace "success" with a Constants value from a JSF library.
Backing Bean Method:
#Override
public String save() {
LOG.info("Called");
return "success";
}
For your issue, you'll find Omnifaces' <o:importConstants /> so useful (that's what I use in my own projects). That way you can import your constants file in your JSF page (I use my master page template for that).
<o:importConstants
type="com.mycompany.NavigationResults" />
This way you can access your NavigationResults values both from Java code and JSF tags (EL scope).
public abstract class NavigationResults {
public static final String SUCCESS = "success";
public static final String HOME = "home";
}
Use it in your managed beans:
public String save() {
LOG.info("Called");
return NavigationResults.SUCCESS;
}
In your buttons or links:
<h:button value="Go home" outcome="#{NavigationResults.HOME}" />

JSF ElResolver Returns wrong type with generics

I try to set the values of a selectManyCheckbox to my testBean backing bean.
If I use a property of type List<String> instead of Attributed<List<String>> it works perfectly. It is the workaround I'm using currently.
But on my backing bean I have a generic object which contains the List.
The javax.el.BeanELResolver resolve this to an Object. Which is correct due to Type erasure.
I tried to implement a custom ElResolver. But I should know to which type to convert the object to. It isn't obviously always a List. I have the information in the xhtml pages. So I hoped I could pass some child element which would contain the information, but could not find a way to access the child element from the ElResolver.
A Custom converted does not work either as it converts selectItems, not the List.
Here is the simplest form
<h:form>
<p:selectManyCheckbox value="#{testBean.attributed.value}" >
<f:selectItems value="#{testBean.selection}" />
</p:selectManyCheckbox>
<p:commandButton action="#{testBean.execute}" value="do it" />
</h:form>
and the bean
private Attributed<List<String>> attributed = new Attributed<>();
public Map<String, String> getSelection() {
return ImmutableMap.<String, String> of("key1", "value1", "key2", "value2");
}
public static class Attributed<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public Attributed<List<String>> getAttributed() {
return attributed;
}
public void setAttributed(Attributed<List<String>> attributed) {
this.attributed = attributed;
}
So the question is:
Is there a way to set the value to testBean.attributed.value directly and with the correct type.
Is it possible by defining a custom ElResolver, or are there other way to do it?

How To Prepopulate Checkboxes With Struts2 and Jquery?

I am trying to determine the best/easiest way to prepopulate certain checkboxes created using Struts2 form tags. My application is a "normal" three tier setup, using Struts2 on the controller layer.
Before I really, really dig deep here, does the tag support creating the list of all possible checkboxes, then populating it (say, via the below action)?
Sample action:
public class UserManagementAction extends ActionSupport implements Preparable {
private List<String> allRoles;
private List<String> rolesToPrepopulate;
// get/set methods
public void prepare() throws Exception {
// populate the allRoles and rolesToPrepopulate lists
}
public String execute() throws Exception {
return INPUT;
}
(Note: assume that struts.xml has been configured with which JSP to return for INPUT)
Thanks for any help.
Jason
What I would do is a new object class and use it as for checkboxes.
For example:
public class StrutsCheckbox {
private Integer id;
private Boolean selected;
...
}
And in prepare() method you can set selected field as you wish (and also id to all of them).
Next in JSP:
<s:iterator value="allRoles">
<s:checkbox name="selected" id="selected" fieldValue="%{id}" value="%{selected}"/>
</s:iterator>
And then in submit action Collection selected will be filled with ids.
public class UserManagementAction extends ActionSupport implements Preparable {
private List<StrutsCheckbox> allRoles;
private List<StrutsCheckbox> rolesToPrepopulate;
private List<Integer> selectedCheckboxes;
// get/set methods
public void prepare() throws Exception {
// populate the allRoles and rolesToPrepopulate lists
// fill and set allRoles and/or rolesToPrepopulate
}
public String execute() throws Exception {
return INPUT;
}
public String submit() throws Exception {
// list selectedCheckboxes is filled with selected fields id's
return INPUT;
}
Maybe with some corrections it will work, but the main idea is here.

Resources