JSF2.0 converter need for SelectItems? - java

I got folowing message:
Value is no String (class=org.xxx.Foo, value=org.xxx.Foo#366d5595) and component j_id17:j_id114:j_id125with path: {Component-Path : [Class: org.ajax4jsf.framework.ajax.AjaxViewRoot,ViewId: /foo.xhtml][Class: org.ajax4jsf.ajax.html.Include,Id: j_id17][Class: javax.faces.component.html.HtmlForm,Id: j_id114][Class: javax.faces.component.html.HtmlSelectOneMenu,Id: j_id125]} does not have a Converter.
Xhtml:
<h:selectOneMenu value="#{bar.foo}">
<f:selectItem itemValue="#{bar.foos}" />
</h:selectOneMenu>
Foo is:
import javax.faces.model.SelectItem;
#Audited
#Entity
#Table(name= "foo")
#AccessType("property")
public class Foo extends SelectItem implements Serializable{
....
}
Why do i need a converter to convert from SelectItem to SelectItem?

The problem arises when JSF tries to glean the selected value from Foo during display and when it tries to get Foo back from the selected value during a postback. As BalusC mentioned, extending SelectItem isn't a good approach. You have one of two regular options: manually handling the selection or using converters.
Converters are wonderful for adapting pretty much any type of Object so that they can be directly referenced and presented via UI elements. Unfortunately, converters may require extra steps when a conversion isn't simple.
I noticed the #Entity annotation, so I'm assuming you are trying to display a list of records from which the user can choose. 90% of the time, such selections are intended to get a record's primary key rather than the record itself so that it can be used in subsequent queries or business logic. For such situations a manual selection is more effective. However, if you also need to get record content, then a converter is better suited as it would handle the lookup logic and let your business logic work directly with the record.
I'm not going to dictate which method you should choose, but since your original problem was centered around the manual approach, I'll offer this solution. Let's assume your new simplified Foo looks like this.
public class Foo {
private long id;
private String label;
public Foo( long id, String label ) {
this.id = id;
this.label = label;
}
public long getId() {
return id;
}
public void setId( long id ) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel( String label ) {
this.label = label;
}
}
A simple FooCntrl bean as given below would provide presentation information and handle the selection's postback.
#Named
#ViewScoped
public class FooCntrl implements Serializable {
private long selected = 0;
// Stub for what an EntityManager would normally provide.
public List<Foo> getRecords () {
List<Foo> fooList = new ArrayList<Foo>();
fooList.add( new Foo( 11, "Paul" ) );
fooList.add( new Foo( 23, "John" ) );
fooList.add( new Foo( 32, "George" ) );
fooList.add( new Foo( 47, "Ringo" ) );
return fooList;
}
public long getSelected() {
return selected;
}
public void setSelected( long selected ) {
this.selected = selected;
System.out.println( "You picked record id: " + selected );
}
public List<Foo> getFooList() {
return getRecords();
}
}
This in turn drives your UI selection menu.
...
<h:form>
<h:selectOneMenu value="#{fooCntrl.selected}">
<f:selectItem itemValue="0" itemLabel="Select One..." />
<f:selectItems value="#{fooCntrl.fooList}" var="r" itemLabel="#{r.label}" itemValue="#{r.id}"/>
</h:selectOneMenu>
<h:commandButton value="Submit" />
</h:form>
...
This is just one variant. I'm certain that some will disagree with it and recommended converters all the way or even recommend another manual approach. My goal is to give you something that you can move forward with. I'll leave it up to you to refine your design methodology and style at your own pace :).

Related

JSF Java Beans - initialize and proceed

I am new to JavaBeans and I need a little help to keep my first little JSF-project going.
I am writing a little web application where a user can search with certain criteria for buildings. So the user enters in the search form 'location', 'property type', 'asking price', 'number of rooms' and 'living space'.
My managed bean accept the requiry with setter/getter and now the data is to be transmitted to a SQL class, where they are processed and matching search results are returned. It sounds simple, but I can not find a solution.
My managed bean looks like this now:
package beans
//import statements
...
#ManagedBean
#RequestScoped
public class PropertySearchBean {
private String _place
private String _propertyType
private double _askingPrice
private int _rooms
private double _livingSpace
public ArrayList<SearchResults> results = new ArrayList<SearchResults>();
// empty constructor
...
// getter and setter for these 5 user inputs
...
public void initializeSearchResults() {
// do the SQL query, recieve search results
// add it as a new object of 'SearchResults'
SQLPropertySearch search = new SQLPropertySearch(_place, _propertyType,
_askingPrice, _rooms, _livingSpace);
ArrayList<Integer> idResults = search.getPropertyIDlist();
SQLProperty property;
if(!idResults.isEmpty()) {
for(int i=0; i<idResults.size(); i++) {
property = new SQLProperty(idResults.get(i));
results.add(new SearchResults(
property.getPropertyID(),
property.getPropertyName(),
// and so on..
));
}
}
}
public static class SearchResults {
int propertyID;
String propertyName;
// and so on..
public SearchResults(int propertyID, String propertyName) {
this.propertyID = propertyID;
this.propertyName = propertyName;
// and so on..
}
// getter and setter
public int getPropertyID() {
return propertyID;
}
public void setPropertyID(int propertyID) {
this.propertyID = propertyID;
}
// and so on..
}
public ArrayList<SearchResults> getResults() {
return results;
}
}
In my XHTML-file I go through each entry of my ArrayList results.
It looks like this:
<ui:repeat var="res" value="#{PropertySearchBean.results}">
<p>#{res.propertyID}</p>
<p>#{res.propertyName}</p>
</ui:repeat>
I don't have an idea how to initialize the ArrayList, because first thing to do is the search itself, with the user input.
I am thankful for any kind of help!
You've removed the getters and setters from your example to improve readability. I'll provide one implementation here to ensure a common understanding (especially regarding the leading underscores).
public String getPlace() {
return _place;
}
public void setPlace(String place) {
this._place = place;
}
The property 'place' will be accessible within your view by using the value binding #{propertySearchBean.place}(see below).
Your code is meant to perform a search. Therefore you'll have to transfer user input from your XHTML file (view) to your managed bean. To do so you need to add a form to your view. Each search query parameter is bound to your bean using a specific value binding. Additionally the form contains a <h:commandButton> tag which finally triggers initialization of the result list.
<h:form>
<h:outputLabel for="place" value="Place:" />
<h:inputText id="place" value="#{propertySearchBean.place}" />
<!-- Additional fields -->
<h:commandButton action="#{propertySearchBean.initializeSearchResults}"
value="Search"/>
</h:form>
Note: You've used the following code in your example
<ui:repeat var="res" value="#{PropertySearchBean.results}">
Make sure that the first letter of your bean name is lower-case (propertySearchBean instead of PropertySearchBean). So this needs to be updated to
<ui:repeat var="res" value="#{propertySearchBean.results}">

how to access two different java entities as parameters in backing bean method

Mojarra 2.1.5 / Java
I have two entities : i.e.
class Primary { String name; String age }
class Second { String dept; String hour }
...
In my managed bean I developed a function to generate PDF regarding my front-end prime-faces radio button (Primary or Second).
If I select in radio button the Primary option, the managed bean method will fire generatePDF() and inside the generatePDF I have :
Primary pr = new Primary();
pr.name = xxxxx;
pr.age = yyyyy;
...
...
But how can I do to re-utilize the same method generatePDF for both entities (Primary and Second ? I need to access both entity properties regarding my radio selection.
I need to instantiate the entities dynamically (Or I instantiate Primary or I intantiaty Second at a time)
What about do something like this.
interface Pdfeable{ String writeToPDF();}
class Primary implements Pdfeable { String name; String age }
class Second impleaments Pdfeable { String dept; String hour }
Just override with the statements you want to send data to the PDF.
class Primary implements Pdfeable {
String name; String age;
public String writeToPDF(){
return getName() + "" + getAge();
}
}
And write your code using the interface definition not concrete classes.
Assuming as per your question you need one class instantiation at a time as per radio button selection ,I would suggest you should create a valueChangeListener to your radio button.I have hardcoded the values of radio selectItem you can use any way either by bean-binding or hardcoded.
<h:selectOneRadio value="#{myBean.myRadioValue}" ... onclick="this.form.submit();" valueChangeListener="#{myBean.generatePDF}">
<f:selectItem itemValue="Radio1" itemLabel="Primary-radio" />
<f:selectItem itemValue="Radio2" itemLabel="Secondary-radio" />
</h:selectOneRadio>
This code will submit the form where the radio button are contained when the onclick Javascript event is detected. On the server side, the action generatePDF will be executed. In this method, you can do your requiste as on Submit action getter and setter will be called and you can check which radio is selected by comparing using if () and do your stuff:
public void generatePDF(ValueChangeEvent evt) {
if(getMyRadioValue.equals(Radio1)){
Primary pr = new Primary();
pr.name = xxxxx;
pr.age = yyyyy;
}
else if(getMyRadioValue.equals(Radio2)){
Secondary s = new Secondary();
s.dept = xxx;
s.hour = yyyy;}
...
...
}

Transforming Form Field to Object on Submit

I'm rather new to Play Framework so I hope this is intelligible.
How can I tell play to map a form element to an Object field in the Form's class?
I have a form with a select dropdown of names of objects from my ORM. The values of the dropdown items are the ID field of the ORM objects.
The form object on the Java side has a field with the type of the ORM object, and a setter taking a string and translating it to the object, but on form submission I only get a form error "Invalid Value" indicating the translation is not taking place at all.
My template has a form component:
#helper.select(
createAccountForm("industry"),
helper.options(industries)
)
Where industries is defined in the template constructor by : industries: Map[String, String]
and consists of ID strings to User-Readable names.
My controller defines the class:
public static class CreateAccountForm {
public String name;
public Industry industry;
public void setIndustry(String industryId) {
this.industry = Industry.getIndustry(Integer.parseInt(industryId));
}
}
EDIT: I was doing the setter in the class because this answer indicated to do so, but that didn't work.
EDIT2:
Turns out the setter method was totally not the way to go for this. After banging my head a bit on trying to get an annotation working, I noticed the Formatters.SimpleFormatter and tried that out. It worked, though I don't understand why the extra block around it is necessary.
Global.java:
public class Global extends GlobalSettings {
// Yes, this block is necessary; no, I don't know why.
{
Formatters.register(Industry.class, new Formatters.SimpleFormatter<Industry>() {
#Override
public Industry parse(String industryId, Locale locale) throws ParseException {
return Industry.getIndustry(Integer.parseInt(industryId));
}
#Override
public String print(Industry industry, Locale locale) {
return industry.name;
}
});
}
}
Play is binding the form to an object for you when you use it like described in the documentation: https://github.com/playframework/Play20/wiki/JavaForms
So your controller should look like:
Form<models.Task> taskForm = form(models.Task.class).bindFromRequest();
if (taskForm.hasErrors()) {
return badRequest(views.html.tasks.create.render(taskForm));
}
Task task = taskForm.get();
The task object can have a Priority options list. And you use it in the form (view) like:
#select(editForm("priority.id"), options(Task.priorities), 'class -> "input-xlarge", '_label -> Messages("priority"), '_default -> Messages("make.choice"), 'showConstraints -> false, '_help -> "")
Notice that I am using priorities.id to tell play that a chosen value should be binded by a priority ID. And of course getting the priorities of the Tasks:
public static Map<String, String> priorities() {
LinkedHashMap<String, String> prioritiesList = new LinkedHashMap<String, String>();
List<Priority> priorities = Priority.getPrioritiesForTask("task");
for (Priority orderPrio : priorities) {
prioritiesList.put(orderPrio.getId().toString(), orderPrio.getDescription());
}
return prioritiesList;
}

How to bind complex types in play-framework 2.0

I have a model class in the following structure:
public class User {
public String name;
public Long id;
}
public class Play {
public String name;
public User user;
}
Now i want to have a form based on Play class. So I have an editPlay view which takes Form[Play] as an input.
In the view I have a form which calls an update action on submit:
#form (routes.PlayController.update())
{..}
but I cannot find the right way to bind the user field in a way I'll receive it properly in the controller:
Form<Play> formPlay = form(Play.class).bindFromRequest();
Play playObj = formPlay.get();
According to the API, Form.Field value is always a string. Is there some other way to automatic bind an input to the User Object?
Thanks
You can make use of custom DataBinder
In the play.scla.html:
#form (routes.PlayController.update())
{
<input type="hidden" name="user" id="user" value="#play.user.id"/>
}
in your method in the controller
public static Result update()
{
// add a formatter which takes you field and convert it to the proper object
// this will be called automatically when you call bindFromRequest()
Formatters.register(User.class, new Formatters.SimpleFormatter<User>(){
#Override
public User parse(String input, Locale arg1) throws ParseException {
// here I extract It from the DB
User user = User.find.byId(new Long(input));
return user;
}
#Override
public String print(User user, Locale arg1) {
return user.id.toString();
}
});
Form<Play> formPlay = form(Play.class).bindFromRequest();
Play playObj = formPlay.get();
}
I'm not quite sure I understand your question, but basically I have been handling forms like this:
final static Form<Play> playForm = form(Play.class);
...
public static Result editPlay(){
Form<Play> newPlayForm = form(User.class).bindFromRequest();
Play newPlay = newPlayForm.get();
....
}
I serve and render the template from an action using:
return ok(play_form_template.render(playForm));
Then in the template:
#(playForm: Form[Play])
#import helper._
#helper.form(action = routes.Application.editPlay()) {
#helper.inputText(playForm("name"))
...
}

#ManagedProperty in backing bean - setting getters and setters

According this article, I've implemented #ManagedProperty(value="#{settings}") to my backing bean:
BEAN Bde.java:
#Entity
#Table(name="bdeDATA")
#ViewScoped
#ManagedBean(name="BDE")
public class Bde implements Serializable
{
/**/
private static final long serialVersionUID = -705775502999920673L;
#Transient
#ManagedProperty(value = "#{settings}")
private Settings settings;
#Id
private Date create_date;
private Integer person_ID;
public Date getCreate_date() {
return create_date;
}
public void setCreate_date(Date create_date) {
this.create_date = create_date;
}
public Integer getPerson_ID() {
return person_ID;
}
public void setPerson_ID(Integer person_ID) {
this.person_ID = person_ID;
try
{
Settings.PWKITEM = (Pwk)Tools.find(person_ID);
if (Settings.PWKITEM != null) settings.setUserfound(true); /// PROBLEMATIC
}
catch (Exception e)
{
Tools.setErrorMessage("NOT FOUND "+e.getMessage());
}
}
// ManagedProperty settings ---------------------------------------------
public Settings getSettings() {
return settings;
}
public void setSettings(Settings settings) {
this.settings = settings;
}
public void setUserfound (boolean userfound){
settings.setUserfound(userfound);
}
public boolean isUserfound() {
return settings.isUserfound();
}
}
Settings.java:
#SessionScoped
#ManagedBean(name="settings")
public class Settings implements Serializable
{
/**/
private static final long serialVersionUID = 8613411699115714416L;
public static Pwk PWKITEM = new Pwk();
private boolean userfound = false;
public boolean isUserfound() {
return userfound;
}
public void setUserfound(boolean userfound) {
this.userfound = userfound;
}
}
XHTML (ajax call setPerson_ID):
<h:inputText id="persId" value="#{bean.bdeitem.persId}">
<f:ajax event="blur" render="name" execute="#this" />
</h:inputText>
<h:inputText id="name" value="#{bean.pwkitem.name}"/>
Problem is in try/catch:
without the condition, object is found.
when I change the condition for example to if (Settings.PWKITEM != null) System.out.println("HELLO"), HELLO is writen to console.
if i try to add the userfound setter, it is catched ("NOT FOUND").
What I'm doing wrong?
Your question looks seriously confusing. You first show some bean code and then immediately say "I though that is an ajax problem,", before even mentioning any kind of problem. The rest of the question is not much different.
To directly answer the last part of your question though:
Ican't understand, why it find the item an writes the correct name to console, and immediatelly after that, it writes catch exception not found....????
You are accessing Settings statically. The instance you have declared at the class level seems to be useless. It's fully possible that if Tools.find throws an exception and thus no new value is assigned, that there is still an old value in the static Settings.PWKITEM field. There is nothing strange about that.
Do note that the log reads from top to bottom. So it's not that "***" is printed and then the exception is thrown, but the exception is first thrown and "Not Found" is printed, and only thereafter "***" is printed.
Additionally, your approach to all of this looks problematic. Declaring an Entity to also be a (JSF) backing bean is rarely a good idea. Using references to some kind of Service or DAO classes from within an entity is also not always a good idea, but doing this in a method that is supposedly a simple setter for an ID simply looks wrong.
Then using static references is even more wrong and to top if off, using underscores in method and non-static variable names goes against the common Java code convention.

Categories