Converting to long and validate - validation

I have a Facelets page with a form with ICEfaces components. empId is a long type property, which has to be checked if null or not in the bean. It is taken as String in the form, and I am converting that to long type using Long.valueof(empId).longValue(); in order to pass it to DAO to check against DB column.
Is this the way we are supposed to do it? Or are there another ways?

You'd like to use a Long property instead of a String property to enforce automatic conversion to Long by JSF/EL (it has namely builtin conversion for standard Number, Boolean and Enum types).
private Long empId;
with
<h:inputText value="#{bean.empId}" />
You'd like to use required attribute to validate required input.
<h:inputText value="#{bean.empId}" required="true" />
Any conversion or validation error message can be shown using <h:message>.
<h:inputText id="empId" value="#{bean.empId}" required="true" />
<h:message for="empId" />
You can if necessary change the conversion and required message as follows:
<h:inputText id="empId" value="#{bean.empId}" required="true"
requiredMessage="Please enter employee ID."
converterMessage="Please enter digits only." />
<h:message for="empId" />
This way you don't need to perform any conversion/validation in the bean's action method, which would be the wrong place for it anyway. You should use JSF builtin converters or a custom Converter for conversion and JSF builtin validators or a custom Validator for validation. The backing bean property should hold the right type already and the backing bean action method should not do any conversion/validation.
I only wonder if that DAO method call to check the column can't better be handled by a custom Validator, but that depends all on the concrete functional requirement which is unclear from the question.

Related

Conditional validation without binding attribute

I'm dealing with a legacy code base and come across a situation when it's necessary to validate a field "fieldToValidate" if some other field "otherField" has some value (otherwise field is not validated). However the field "otherField" doesn't have a binding attribute.
I can add a binding and then update code like this:
<h:inputTextarea id="fieldToValidate" value="#{MyBean.fieldToValidate}"
required="#{MyBean.otherField != 'special_value'}" />
However there is a plenty of places where validation should be added and I don't want to modify backing beans. Is there a way to implement validation without adding "binding"?
Validation with some JS library is not a option.
You do not necessarily need to bind it to a bean property. Just omit the MyBean. part to bind it to the view scope directly.
<h:selectOneMenu binding="#{otherField}" ... />
...
<h:inputTextarea ... required="#{otherField != 'special_value'}" />
See also:
JSF component binding without bean property
What is component binding in JSF? When it is preferred to be used?

How to pass the event parameter when attaching an listener to a composite component

I tried to attach an event-listener to a composite component as follows:
<cc:interface>
<cc:attribute name="listener" method-signature="void listener(javax.faces.event.ComponentSystemEvent)" />
<cc:attribute name="value" />
</cc:interface>
<cc:implementation>
<h:inputText value="#{cc.attrs.value}">
<f:event type="preRenderComponent" listener="#{cc.attrs.listener}" />
</h:inputText>
</cc:implementation>
with the using page having this:
<ofc:testComp value="#{testAction.testInt}" listener="#{testAction.doWhatever}" />
and the backing bean like so:
public void doWhatever(ComponentSystemEvent event) {
System.out.println(testInt);
System.out.println("I was here");
}
This results in a PropertyNotFoundException: doWhatevercannot be found on testAction When searching the web I found this very similar solution. The main difference here is that the event parameter has been omitted. When I do the same in my scenario, it works (which I find confusing, because the documentation for f:ajax and f:event states the listener must to conform to void listener(AjaxBehaviorEvent) and void listener(ComponentSystemEvent) respectively)
The problem is: I'm trying to do all of this exactly because I need to get back to the original sender of the event via event#getComponent So the question is: Is there a way to pass the event parameter in this kind of setup?
Background: I need to perform some additional validation on a range of fields. Basically, I want to hook into the lifecycle after the model has been updated, perform some calculation and possibly abort before the invoke application phase if values don't fit. The offending field needs to be marked.
I played around with the normal validation mechanism for a while, but the calculation uses the model values, which will not have been updated yet at that point. I am aware, that even if I get the above code running, preRenderView will be too late to stop actions, but I am thinking about keeping an hidden input, which currently does the job of failing validation under the hood, and just adding the listener to actually mark the real offending field. But for this, I need the event ... any ideas?
Thanks in advance.
Update: this answer here uses the same principle, but also runs into problems as soon as the parameter is added - only I get a different error.

JSF 2.0 Displaying all validation messages of multiple validators

I have an h:inputText element with more than one validators, eg.:
<h:inputText id="myId" value="#{some.value}">
<f:validator validatorId="validatorOne/>
<f:validator validatorId="validatorTwo/>
</h:inputText>
<h:message for="myId"/>
Now if I implement my validators to throw a ValidatorException, the second validator won't run, even if it would fail as well.
But I'd like both validators to run and to diplay both error messages in case both validations fail.
I've already tried not to throw ValidatorException like this:
facesContext.addMessage(uiComponent.getClientId(), facesMessage);
((UIInput)uiComponent).setValid(false);
But the h:message won't display both of the error messages, although I can see them if I use h:messages.
How is it possible to display all validation error messages?
That's the way how JSF validators are specified to work. The validators are fired in the order they're declared on the component and if one of them fails, then the remnant won't be fired.
If using <h:messages> is really not an option for some unclear reason (perhaps you weren't aware about its for attribute which works the same way?), then your best bet is creating another validator which in turn delegates to the both validators and merges the caught validator exceptions into one.

a question about the design Validation using JSF framework

In software design sort of way, what is best: checking unique input (e.g username) in the DB using a JSF Validator, or using the Controller (managed-bean).
Apparently, in JSF framework, I can't use #EJB in the Validator, so in case I use the Validator for the checks, then I would have to connect to the DB in another way (jdbc connection or something).
In case I check this one in the Controller, I would have to put some logic that is not necessary a part of the process (for example: createUser method).
So, what is the best way according to the JSF framework?
Apparently, in JSF framework, I can't use #EJB in the Validator, so in case I use the Validator for the checks, then I would have to connect to the DB in another way (jdbc connection or something).
That's right. A common workaround for this is to declare and use the validator as a #ManagedBean.
E.g.
#ManagedBean
#RequestScoped // Can be #ApplicationScoped if it does not hold any state.
public class UsernameValidator implements Validator {
#EJB
private UserService userService;
// ...
}
with
<h:inputText validator="#{usernameValidator.validate}" />
or
<h:inputText>
<f:validator binding="#{usernameValidator}" />
</h:inputText>

Get Request and Session Parameters and Attributes from JSF pages

I'm using JSF with facelets and I need to get the request and session parameters inside the JSF page. In JSP pages I got this parameter like that: "${requestScope.paramName}" or "${sessionScope.paramName}". But now after using JSF there are only beans and you can't get any value except bean attributes.
NOTE: The session attributes what I need is auto filled using acegi security so I can't get any access to them.
So what to do now?
You can get a request parameter id using the expression:
<h:outputText value="#{param['id']}" />
param—An immutable Map of the request parameters for this request, keyed by
parameter name. Only the first value for each parameter name is included.
sessionScope—A Map of the session attributes for this request, keyed by
attribute name.
Section 5.3.1.2 of the JSF 1.0 specification defines the objects that must be resolved by the variable resolver.
You can also use a bean (request scoped is suggested) and directly access the context by way of the FacesContext.
You can get the HttpServletRequest and HttpServletResposne objects by using the following code:
HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpServletResponse res = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
After this, you can access individual parameters via getParameter(paramName) or access the full map via getParameterMap() req object
The reason I suggest a request scoped bean is that you can use these during initialization (worst case scenario being the constructor. Most frameworks give you some place to do code at bean initialization time) and they will be done as your request comes in.
It is, however, a bit of a hack. ;) You may want to look into seeing if there is a JSF Acegi module that will allow you to get access to the variables you need.
You can either use
<h:outputText value="#{param['id']}" /> or
<h:outputText value="#{request.getParameter('id')}" />
However if you want to pass the parameters to your backing beans, using f:viewParam is probably what you want. "A view parameter is a mapping between a query string parameter and a model value."
<f:viewParam name="id" value="#{blog.entryId}"/>
This will set the id param of the GET parameter to the blog bean's entryId field. See http://java.dzone.com/articles/bookmarkability-jsf-2 for the details.
You can like this:
#{requestScope["paramName"]} ,#{sessionScope["paramName"]}
Because requestScope or sessionScope is a Map object.
You can also use a tool like OcpSoft's PrettyFaces to inject dynamic parameter values directly into JSF Beans.
Assuming that you already put your object as attribute on the session map of the current instance of the FacesContext from your managed-bean, you can get it from the JSF page by :
<h:outputText value="#{sessionScope['yourObject'] }" />
If your object has a property, get it by:
<h:ouputText value="#{sessionScope['yourObject'].anyProperty }" />
Are you sure you can't get access to request / session scope variables from a JSF page?
This is what I'm doing in our login page, using Spring Security:
<h:outputText
rendered="#{param.loginFailed == 1 and SPRING_SECURITY_LAST_EXCEPTION != null}">
<span class="msg-error">#{SPRING_SECURITY_LAST_EXCEPTION.message}</span>
</h:outputText>
In the bean you can use session.getAttribute("attributeName");

Resources