I am working with settings part in my project. I want to get the form attributes from the DB like maxlength, minlength, pattern etc.
I want to use my bean class variable as a pattern String. Is that Possible? minlength, maxlength attributes works fine using bean class variable, but validateRegex is not working
Bean code
#Service
class CategoryBean {
String categoryNamePattern;
String showForm(){
categoryNamePattern = "([a-zA-Z ]*[a-zA-Z]+[a-zA-Z ]*)";
return "myform.xhtml";
}
}
myform.xhtml With bean class variable for regex pattern
<p:inputText id="name" value="#{categoryBean.selectedCategory.name}">
<f:validateRegex for="name" pattern="#{categeoryBean.categoryNamePattern}"/>
</p:inputText>
myform.xhtml This Works fine with pattern defined inside
<p:inputText id="name" value="#{categoryBean.selectedCategory.name}">
<f:validateRegex for="name" pattern="([a-zA-Z ]*[a-zA-Z]+[a-zA-Z ]*)"/>
</p:inputText>
Finally I did with validator tag. wrote a new validator method
This works fine.
#Service
class CategoryBean {
String catNamePattern;
String showForm(){
categoryNamePattern = "([a-zA-Z ]*[a-zA-Z]+[a-zA-Z ]*)";
return "myform.xhtml";
}
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (catNamePattern != null) {
RegexValidator regexValidator = new RegexValidator();
regexValidator.setPattern(categoryNamePattern);
regexValidator.validate(context, component, value);
}
}
}
<p:inputText id="name" value="#{categoryBean.selectedCategory.name}">
<f:validateRegex for="name" pattern="#{categeoryBean.categoryNamePattern}" validator="#{categoryBean.validate}" />
</p:inputText>
Related
I want to create very simple JSF web page which I would like to use for price calculation:
<h:form>
<h:outputText value="Number of Computers"/>
<h:panelGroup layout="block" id="desktopClients_select" style="padding-top: 3px;" styleClass="text">
<h:inputText id="desktopClients" value="#{pricingCalculator.computers}">
<f:ajax event="change" render="#form" listener="#{pricingCalculator.calculateTotalPrice}"/>
</h:inputText>
</h:panelGroup>
<h:outputText value="Email support incidents"/>
<h:panelGroup layout="block" id="email_support_incidents" style="padding-top: 3px;" styleClass="text">
<h:inputText id="email_support_incidents_text" value="#{pricingCalculator.emailSupportIncidents}">
<f:ajax event="change" render="#form" listener="#{pricingCalculator.calculateTotalPrice}"/>
</h:inputText>
</h:panelGroup>
<h:outputText value="Phone support incidents"/>
<h:panelGroup layout="block" id="phone_support_incidents" style="padding-top: 3px;" styleClass="text">
<h:inputText id="phone_support_incidents_text" value="#{pricingCalculator.phoneSupportIncidents}">
<f:validateLongRange minimum="1" maximum="150" />
<f:ajax event="change" render="#form" listener="#{pricingCalculator.calculateTotalPrice}"/>
</h:inputText>
</h:panelGroup>
<h:outputText value="Total price"/>
<h:panelGroup layout="block" id="total_price" style="padding-top: 3px;" styleClass="text">
<h:outputText value="#{pricingCalculator.calculateTotalPrice}"/>
</h:panelGroup>
</h:panelGrid>
</h:form>
Bean:
#Named
#ViewScoped
public class PricingCalculator implements Serializable
{
private int computers;
private float emailSupportIncidents;
private float phoneSupportIncidents;
private float totalPrice;
// Prices for each component and service
private final float computers_price = 299;
private final float emailSupportIncidents_price = 300;
private final float phoneSupportIncidents_price = 150;
public String getCalculateTotalPrice()
{
totalPrice = (computers_price * computers)
+ (emailSupportIncidents_price * emailSupportIncidents)
+ (phoneSupportIncidents_price * phoneSupportIncidents);
String result = Float.toString(totalPrice);
return result;
}
public int getComputers()
{
return computers;
}
public void setComputers(int computers)
{
this.computers = computers;
}
public float getEmailSupportIncidents()
{
return emailSupportIncidents;
}
public void setEmailSupportIncidents(float emailSupportIncidents)
{
this.emailSupportIncidents = emailSupportIncidents;
}
public float getPhoneSupportIncidents()
{
return phoneSupportIncidents;
}
public void setPhoneSupportIncidents(float phoneSupportIncidents)
{
this.phoneSupportIncidents = phoneSupportIncidents;
}
public float getTotalPrice()
{
return totalPrice;
}
public void setTotalPrice(float totalPrice)
{
this.totalPrice = totalPrice;
}
}
When I insert some value into the input fields I would like to recalculate the total price. I have now two issues: I get exception serverError: class javax.el.MethodNotFoundException /pricing_calculator.xhtml #115,136 listener="#{pricingCalculator.calculateTotalPrice}": Method not found: com.web.common.PricingCalculator#22939533.calculateTotalPrice(javax.faces.event.AjaxBehaviorEvent)
and when I insert new value previous one is set to zero. It's not remembered properly.
#BalusC has already given you the answer, but to be more explicit, here's a quote from Oracle's Java EE 6 tutorial (which you should read) about Method Expressions:
Method expressions can be used only in tag attributes and only in the
following ways:
With a single expression construct, where bean refers to a JavaBeans component and method refers to a method of the JavaBeans
component:
<some:tag value="#{bean.method}"/>
[...]
That said, rename getCalculateTotalPrice to calculateTotalPrice
Edit: There's also an inconsistency between the expected signatures of the following method calls:
<f:ajax listener="#{pricingCalculator.calculateTotalPrice} .../>
which expects a MethodExpression refering to a calculateTotalPrice(javax.faces.event.AjaxBehaviorEvent) method as clearly stated by the javax.el.MethodNotFoundException
and
<h:outputText value="#{pricingCalculator.calculateTotalPrice}"/> which expects a java.lang.String that can refer to a bean property, or the return value of a method call.
Here, the <h:outputText> value is probably meant to be set to the totalPrice property, so it should be: <h:outputText value="#{pricingCalculator.totalPrice}"/>
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.
Ok, so I get this error and found no solution working for me (I tried around a lot with annotations like #FacesConverter or #Named instead #ManagedBean etc.) If anybody could point me to the right direction, that would be awesome. BalusC mentioned, that this particular error means, that the converter cannot be found, but the Converter is getting called, as I can see in log messages of JBoss (see log.info calls below in the Converter code). At least I don't get NullPointerExceptions from the Converter anymore (although I can't reproduce why). I'm getting a bit frustrated with JSF, but I'm sure it's my fault and I have overseen something obvious?
The code should be simple enough, I want to set zero, one or more Tags for a Link entity (newLink.tags) with means of a selectManyCheckbox:
This is my XHTML form:
<h:form id="create_link_form" rendered="#{authController.loggedIn}">
<h3>Enter a new Link here:</h3>`
<h:panelGrid columns="3" columnClasses="titleCell">
<h:outputLabel for="name" value="Name:"/>
<h:inputText id="name" value="#{newLink.name}"/>
<p:message for="name" errorClass="invalid"/>
<h:outputLabel for="url" value="URL:"/>
<h:inputText id="url" value="#{newLink.url}"/>
<p:message for="url" errorClass="invalid"/>
<h:outputLabel for="description" value="Description:"/>
<h:inputText id="description" value="#{newLink.description}"/>
<p:message for="description" errorClass="invalid"/>
<h:outputLabel for="shared" value="Shared?:"/>
<h:selectBooleanCheckbox id="shared" label="Shared?:" value="#{newLink.shared}"/>
<p:message for="shared" errorClass="invalid"/>
</h:panelGrid>
<h:outputLabel for="tags" value="Tags:"/>
<h:selectManyCheckbox label="Tags:" id="tags" value="#{newLink.tags}" converter="#{tagConverter}">
<f:selectItems value="#{tags}" var="tag" itemLabel="#{tag.name}" itemValue="#{tag}"/>
</h:selectManyCheckbox>
<h:inputHidden id="owner" value="#{newLink.owner}" name="{authController.loggedInUserName}"/>
<p>
<h:panelGrid columns="2">
<h:commandButton id="create" action="#{linkController.create}" value="Create"
styleClass="create">
</h:commandButton>
<p:messages styleClass="messages" autoUpdate="true" globalOnly="true"/>
</h:panelGrid>
</p>
</h:form>
And this is my Converter:
#RequestScoped
#ManagedBean
public class TagConverter implements Converter {
#Inject
private Logger log;
#Inject
private TagService tagService;
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if (value != null && value.trim().length() > 0) {
try {
log.info("TTagConverter.getAsObject() => having " + value);
Long id = Long.parseLong(value);
Tag tag = tagService.getTagWithId(id);
log.info("TagConverter.getAsObject() => Tag converted: " + tag);
return tag;
} catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid tag."));
}
} else {
return null;
}
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object object) {
if (object != null) {
if (object instanceof Tag) {
Long id = ((Tag) object).getId();
return id.toString();
} else {
throw new ConverterException(new FacesMessage("There was an Object type error for a "
+ object.getClass() + " in getAsString(" + object + ")"));
}
} else {
return null;
}
}
}
Your managed bean shouldnt implement it.
Create class and implement converter.
#FacesConverter("myConverter")
public class MyConverter implements Converter{
...
}
in your facelets
<h:selectManyCheckbox label="Tags:" id="tags" value="#{newLink.tags}">
<f:selectItems value="#{tags}" var="tag" itemLabel="#{tag.name}" itemValue="#{tag}"/>
<f:converter converterId="myConverter" />
</h:selectManyCheckbox>
Is it clear?
I try learn JSF and faced with problem.
I did use Servlet 2.5, JDK 1.6 and JSF 2.0.6 (com.sun.faces version from pom file).
I have a simple JSF page that has a <h:inputText/> tag for interaction with user
I expect what user fill this h:inputText then click on h:commandButton and on server side i will get backing bean with updated value.
But in my case lifecycle of JSF breaks on process validations, move to render
response and show to user "Parser error!" message
I.e. for simple h:inputText without any validator and converter i receive error message from server side about parsing of h:inputText value.
After some time i figured out what i can create my own converter which will not modify object, just pass String through himself.
I did add my realization of converter to <h:inputText/> and this work.
Question:
In all examples in books and other tutorials nobody used custom converter for <h:inputText/> if inputText is representation of String value of backing bean.
Why all of this tutorials and examples not working for me without custom converter? Where my mistake?
Source codes:
index.xhtml without converter, not worked for me:
<h:form id="UserForm">
<h:outputText value="Insert your first name:" />
<h:inputText id="userNameID" required="true" value="#{userBean.firstName}">
<f:validateLength minimum="5" maximum="25" />
</h:inputText>
<h:message showSummary="true" showDetail="false" for="userNameID" />
<h:commandButton id="submit" action="/view/validator/response?faces-redirect=true"
value="Submit" />
</h:form>
UserBean.java:
#ManagedBean(name = "userBean")
#SessionScoped
public class UserBean implements Serializable {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
MyConverter.java - dummy converter
#FacesConverter(value = "myConverter")
public class MyConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return value;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return value.toString();
}
}
index.xhtml with converter, worked as expected:
<h:form id="UserForm">
<h:outputText value="Insert your first name:" />
<h:inputText id="userNameID" required="true" value="#{userBean.firstName}" converter="myConverter">
<f:validateLength minimum="5" maximum="25" />
</h:inputText>
<h:message showSummary="true" showDetail="false" for="userNameID" />
<h:commandButton id="submit" action="/view/validator/response?faces-redirect=true"
value="Submit" />
</h:form>
The cause of the problem is not visible in the code posted so far, but the key symptom "it fails with a message coming from a so far unidentified converter while it succeeds with an explicit converter" suggests that you've elsewhere in the same project a #FacesConverter(forClass=String.class) which would run automatically on every single String property which doesn't have another converter explicitly specified.
What I am trying to do is that I am taking timeMillis property that stores time in millisecond(that I got my using System.currentTimeMillis()) and convert it to equivalent days,hours,mins and seconds after substracting it from the current time. The main problem is that whenever the converter timeConverter
is called only getAsString function is invoked , getAsObject is not invoked.
Here is the part of my xhtml file which causing the converter to not run properly.
<c:forEach var="p" items="#{statusBean.statusList}">
<h:form>
<div class="status">
<h:commandLink action="#{friendBean.gotoFriendProfile(p.email)}">
<img src="../images/profilePicture/#{p.picture}" style="height: 29px; width: 29px; "/>
<h:outputText value="#{p.statusBy}:"/>
</h:commandLink>
<h:outputText value="#{p.statusmsg}"/>
<h:outputText value="#{p.timeMillis}">
<f:converter converterId="timeConverter"/>
</h:outputText>
<br/>
<c:forEach var="q" items="#{statusBean.commentList(p.statusId)}">
<div class="barcomment">
<br/>
<h:commandLink action="#{friendBean.gotoFriendProfile(q.email)}">
<img src="../images/profilePicture/#{q.picture}" style="height: 29px; width: 29px; "/>
<h:outputText value="#{q.commentBy}:"/>
</h:commandLink>
<h:outputText value=" #{q.comment}"/>
</div>
</c:forEach>
<br/>
<div class="comment">
<p:inputText value="#{statusBean.comment.comment}" styleClass="box" />
<p:commandLink value="Views" action="#{statusBean.update(p.statusId)}" ajax="false" styleClass="link"/>
</div>
Here is the timeConverter class that I have written.
package com.converter;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
public class TimeConverter implements Converter {
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
System.out.println("inside getAsObject");
long time=Integer.parseInt(arg2);
long currentTime=System.currentTimeMillis();
long eclapseTime=time-currentTime;
long secs=eclapseTime/1000;
long days=secs/(60*60*24);
long hours=(secs%(60*60*24))/60*60;
long mins=(secs%(60*60*24)%(60*60))/60;
long secs2=(secs%(60*60*24)%(60*60)%(60));
StringBuffer sb = new StringBuffer();
sb.append(days).append("days").append(hours).append("hours").append(mins).append("mins").append(secs2).append("secs");
String object1 = sb.toString();
return object1;
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
System.out.println("inside getAsString");
String value1 = value.toString();
return value1;
}
}
Why exactly is that a problem?
You're only using the converter here in an UIOutput component:
<h:outputText value="#{p.timeMillis}">
<f:converter converterId="timeConverter"/>
</h:outputText>
The getAsString() is been called to convert the Object model value to a String which can be embedded in the generated HTML output (you know, you can't put Java objects plainly in a HTML string).
However, you're nowhere using it in an UIInput component like <h:inputText>, so there is no means of a submitted String value which needs to be converted to the desired Object in the model, so the getAsObject() will obviously never be called.
Everything is working as designed. It look like that your concrete problem is that you should actually perform the job which you did in getAsObject() in the getAsString() instead.
I think that it would help if you give the methods a bit more sensible argument names:
#Override
public String getAsString(FacesContext context, UIComponent component, Object modelValue) throws ConverterException {
// Write code here which converts the model value to display value.
// This method will be used when generating HTML output.
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) throws ConverterException {
// Write code here which converts the submitted value to model value.
// This method will be used when processing submitted input values.
}
I have a List of strings in my object, and I was hoping to be able to edit them with an a4j:repeat.
Below is my code:
<a4j:repeat value="#{Controller.object.stringList}" var="item" >
<h:panelGrid columns="2">
<h:outputLabel value="ID:" />
<h:inputText value="#{item}" />
</h:panelGrid>
</a4j:repeat>
My problem is that the values of the items never get changed when I submit my form. I've had a look at the livedemo but even after adding the UpdateBean, it still didn't work.
Any ideas?
The objects in your repeat need to follow the bean standard if you want to write back to them. I'm guessing that they are just Strings in your example?
Try this:
public class StringBean {
private String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
along with:
<h:inputText value=#{item.value} />