class not found exception while adding validator class - validation

0 with eclipse and glassfish, in fact i have added a custom validator to validate emai address, and i am getting class not found exception. although i have registered in faces.config too.
here is my validator code
public static final String EmailPattern= "^[_A-Za-z0-9-]+(\\." +
"[_A-Za-z0-9-]+)*#[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*" +
"(\\.[A-Za-z]{2,})$";
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
matcher = pattern.matcher(value.toString());
if(!matcher.matches())
{
FacesMessage message = new FacesMessage("Please enter a valid email address");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
i registerd in faces.config
<validator>
<validator-id>emailvalidator</validator-id>
<validator-class>com.jsf.validators.EmailValidator</validator-class>
</validator>
does someone know what is the problem in it.

Related

Override exception message of SendFailedException getInvalidAddresses()

I use javax.mail dependency spring-boot-starter-mail and i want to override the error message that user get when they provide wrong email or email with domain that dose not exist. How can i override the error message of javax.mail.SendFailedException from the method getInvalidAddresses?
I want to override and pass the user a nice error message. I have my own GlobalExceptionClass which i use for all diffrent Exceptions inside my app:
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler({SendFailedException.class})
private ResponseEntity<MessageResponse> handleSendFailException(SendFailedException sfe){
if (sfe.getInvalidAddresses() != null) {
System.out.println("INVALID ADRESSS");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
MessageResponse("adress is inavlid"));
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
MessageResponse("invalidadress"));
}
}
My Controller Class
#PostMapping("/offers")
public ResponseEntity<MessageResponse> mailOffer(#Valid #RequestBody OffersDto offersDto) throws
MessagingException {
String succMessage = "success.";
offersService.addOffer(offersDto);
offersService.sendMail(offersDto);
return ResponseEntity.ok(new MessageResponse(succMessage));
}
Services class
public Offers sendMail(OffersDto offersDto) throws MessagingException {
///messaging methods, attributes
}
i just replicated this exception handling the same as for other methods, but above code dose not overrides the exception message
You have to try/catch checked exception and in catch or finally block throw new unchecked custom exception, after that handle your Custom exception(you must add attributes of MessagingException to your custom exception for checking statements)
#ExceptionHandler({CustomException.class})

Returning proper value from #AfterThrowing

I am new to String, SpringBoot.
Can we suppress thrown exception in a method annotated with #AfterThrowing?
I mean when an exception is thrown, it will suppress that and will return a default value on behalf of the invoking method?
Say, I have a controller -
#RestController
public class MyRestController implements IRestController{
#Override
#GetMapping("hello-throw")
public String mustThrowException(#RequestParam(value = "name")final String name) throws RuntimeException {
System.out.println("---> mustThrowException");
if("Bakasur".equals(name)) {
throw new RuntimeException("You are not welcome here!");
}
return name + " : Welcome to the club!!!";
}
}
I have created a #AspectJ, as follows -
#Aspect
#Component
public class MyAspect {
#Pointcut("execution(* com.crsardar.handson.java.springboot.controller.IRestController.*(..))")
public void executionPointcut(){
}
#AfterThrowing(pointcut="executionPointcut()",
throwing="th")
public String afterThrowing(JoinPoint joinPoint, Throwable th){
System.out.println("\n\n\tMyAspect : afterThrowing \n\n");
return "Exception handeled on behalf of you!";
}
}
If I run this & hit a ULR like - http://localhost:8080/hello-throw?name=Bakasur
I will get RuntimeException, but, I want to return a default message like - Exception handeled on behalf of you!, can we do it using #AfterThrowing?
I know it can be done using #Around, but around will be called on every hit of the url, that I do not want
What you want to do is Exception Handling on the controller. You don't need to build it yourself, Spring already supports you with some annotations like #ExceptionHandler and #ControllerAdvice. Best would be to follow this example: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc#using-controlleradvice-classes
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.CONFLICT) // 409
#ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do
}
}
#ControllerAdvice
class GlobalDefaultExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
#ExceptionHandler(value = Exception.class)
public ModelAndView
defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// If the exception is annotated with #ResponseStatus rethrow it and let
// the framework handle it - like the OrderNotFoundException example
// at the start of this post.
// AnnotationUtils is a Spring Framework utility class.
if (AnnotationUtils.findAnnotation
(e.getClass(), ResponseStatus.class) != null)
throw e;
// Otherwise setup and send the user to a default error-view.
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}
You should use the fully qualified name of the class before method's name when you're referring to a pointcut. So, you should change #AfterThrowing something like this.
#AfterThrowing(pointcut="packageName.MyAspect.executionPointcut()",
throwing="th")
Please note that packageName is full package name of MyAspect.

Mark inputText as invalid in Invoke Applications phase

I am performing some business rule validations in the Invoke Applications phase, and when there is an error, a custom Exception will be thrown. The custom exception is handled in a custom JSF ErrorHandler, where the input component in question will be marked as invalid, FacesMessages created and validation will be failed on the FacesContext.
Bean
public void performAction() {
if ("aaa".equals(input)) {
// custom exception: arg1 - Error Message, arg2 - clientId
throw new ServiceValidationException("Something went wrong", ":f:input");
}
}
XHTML
<h:form id="f">
<p:inputText id="input" value="#{bean.input}" />
<h:commandButton value="Submit" action="#{bean.performAction}"/>
</h:form>
Custom JSF ErrorHandler
#Override
public void handle() throws FacesException {
try {
Iterator<ExceptionQueuedEvent> unhandledExceptionQueuedEvents = getUnhandledExceptionQueuedEvents().iterator();
if (unhandledExceptionQueuedEvents.hasNext()) {
Throwable exception = unhandledExceptionQueuedEvents.next().getContext().getException();
Throwable rootCause = unwrapRootCause(exception);
if (rootCause instanceof ServiceValidationException) {
ServiceValidationException sve = (ServiceValidationException) rootCause;
JSFComponentUtil.markComponentAsInvalid(sve.getClientId());
// create FacesMessage here etc
...
FacesContext.getCurrentInstance().validationFailed();
return;
}
}
} catch (Exception e) {
logger.error("Error encountered while processing exception, allow default error handling to take over", e);
}
// delegate to Omnifaces Ajax exception handler
super.handle();
}
JSFComponentUtil
public static void markComponentAsInvalid(String componentId) {
UIComponent component = findComponent(componentId);
if (component != null && component instanceof EditableValueHolder) {
EditableValueHolder evh = (EditableValueHolder) component;
if (evh.isValid()) {
evh.setValid(false);
}
} else {
LOG.debug("component not found or is not instance of EditableValueHolder");
}
}
public static UIComponent findComponent(String componentId) {
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
if (viewRoot != null) {
return viewRoot.findComponent(componentId);
}
LOG.debug("View Root is null, returning null");
return null;
}
The Problem
The issue I'm running into is that upon submitting the form via the command button, the page redisplays with the input text field marked as red (expected behavior), however the text that was typed into the field is lost. I want the invalid text entered to remain in the field.
In markComponentInvalid, you can try manually setting the component's value:
evh.setSubmittedValue("aaa");
evh.setValue("aaa");
Of course, instead of hard-coding "aaa" you could add an "input" property to your ServiceValidationClass so that you can pass that value from the action method to the error handler and then to the Util class, e.g.
bean:
throw new ServiceValidationClass ("Something went wrong", ":f:input", input);
error handler:
JSFComponentUtil.markComponentAsInvalid(sve.getClientId(), sve.getInput());
etc.

How to bind custom jsf-validators to programmatically created HTML Elements?

I am using JSF 2.0 and want to attach my custom RangeValidator to a HtmlInputText. In my backing bean, there is a snippet which creates the HTMLInputText. If I add a default validator, my code works like expected. If I add my custom RangeValidator in the same manner (by using FacesContext...) there is an error coming up, more precisely an 'unknown id' error. If I create an instance by using the new keyword, it seems that I am not able to use my accessor-methods, more precisely it seems that my HtmlInputText will use a freshly created RangeValidator-instance at runtime, so property values are minimum = 0 and maximum = 0, my validator is useless. How can I get my custom validator working? Thanks in advance.
// Snippet which creates HTML-Components
if ((integerField.getMaximalValue() != null) && (integerField.getMinimalValue() != null)) { // serverside validation required
// Default JSF Validator - works!
// final LongRangeValidator validator = (LongRangeValidator) FacesContext.getCurrentInstance().getApplication().createValidator(LongRangeValidator.VALIDATOR_ID);
// CustomValidator - ERROR: Unknown validator id;
final RangeValidator validator = (RangeValidator) FacesContext.getCurrentInstance().getApplication().createValidator("mypackage.validators.RangeValidator");
// construct custom validator instance - not working, seems to be a different instance!
// RangeValidator validator = new RangeValidator();
validator.setMaximum(integerField.getMaximalValue());
validator.setMinimum(integerField.getMinimalValue());
inputInteger.addValidator(validator);
}
// Validator
#FacesValidator("RangeValidator")
public class RangeValidator implements Validator {
private int minimum;
private int maximum;
#Override
public void validate(FacesContext context, UIComponent uiComponent, Object value) throws ValidatorException {
//System.out.println("RangeValidator.validate: " + value);
int val = Integer.parseInt((String) value);
if ((val <= this.getMaximum()) && (val >= this.getMinimum())){
// ok
} else {
FacesMessage fm = new FacesMessage();
String message = "Das Feld " + uiComponent.getClientId() + " liefert Validierungsfehler!";
fm.setSeverity(FacesMessage.SEVERITY_ERROR);
fm.setSummary(message);
fm.setDetail(message);
throw new ValidatorException(fm);
}
}
// Accessors
...
}
I found a solution for the problem: RangeValidator needs to implement the Serializable-interface as well and all will work like expected;

Programmatically created form and validation, unhandled faces messages

I create a form by using Apache MyFaces library. The form is related to the
jsf-page by a binding. Moreover I built a TestValidator-class which implements
Validator-interface. My form got shown, I enter my input, validation gots
triggered successfully. Unfortunately I am not able to display corresponding
FacesMessage. I guess I am not able to tell JSF 'Please rerender h:messages
after throwing the validator-Exception'.
What went wrong? Thanks in advance.
#FacesValidator("TestValidator") // class TestValidator
public class TestValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent uiComponent, Object value) throws ValidatorException {
System.out.println("TestValidator.validate: " + value);
if (((String) value).equals("2")){
FacesMessage fm = new FacesMessage();
fm.setSeverity(FacesMessage.SEVERITY_ERROR);
fm.setSummary("TestValidator FEHLER");
fm.setDetail("TestValidator FEHLER");
throw new ValidatorException(fm);
}
}
}
<!-- JSF-Snippet -->
<t:div id="formContainer" binding="#{formsbuilder.form}" />
private Div createFacesMessagesDiv() { // FormsBuilder-Bean-Snippet for creating the container for the FacesMessage
facesMessagesDiv = new Div(); // CORRESPONDING BEAN PROPERTY
facesMessagesDiv.setId("facesMessagesContainer");
facesMessagesDiv.setStyle("color: blue; border: 3px solid green;");
HtmlOutputText introText = new HtmlOutputText();
introText.setId("facesMessagesIntroText");
introText.setValue("FacesMessages - Start: ");
facesMessagesDiv.getChildren().add(introText);
HtmlMessages fms = new HtmlMessages();
fms.setId("facesMessages");
facesMessagesDiv.getChildren().add(fms);
HtmlOutputText outroText = new HtmlOutputText();
outroText.setId("facesMessagesOutroText");
outroText.setValue("FacesMessages - Ende!");
facesMessagesDiv.getChildren().add(outroText);
return facesMessagesDiv;
}
private HtmlAjaxCommandLink createSaveFormButton() { // saveButton after hitting this button, facesMessages should show up;
HtmlAjaxCommandLink saveFormButton = HtmlRendering.createGeneralButton("saveForm" + currentSubForm.getIdAsString(), /* ID */
"#{resources.labels['formsgenerator_saveForm']}",
"#{formsbuilder.submitForm}",
null, /* action */
null, /* actionReturnType */
null, /* onComplete */
"", /* styleClassValueExpression */
"", /* imageValue */
"modifiedContainerDiv");
saveFormButton.setReRender(facesMessagesDiv); // CORRESPONDING BEAN PROPERTY
saveFormButton.setValueExpression("oncomplete", HtmlRendering.createValueExpression("afterGeneralSavingSubForm()");
return saveFormButton;
}
It does not look like you are setting the message correctly.
You forgot to add the FacesMessage to the FacesContext.
Try this:
public void validate(FacesContext context, UIComponent uiComponent, Object value) throws ValidatorException {
System.out.println("TestValidator.validate: " + value);
if (((String) value).equals("2")){
FacesMessage fm = new FacesMessage();
fm.setSeverity(FacesMessage.SEVERITY_ERROR);
fm.setSummary("TestValidator FEHLER");
fm.setDetail("TestValidator FEHLER");
FacesContext.getCurrentInstance().addMessage(null, fm);
throw new ValidatorException(fm);
}
}
Here's a more concise way to write a FacesMessage:
public void validate(FacesContext context, UIComponent uiComponent, Object value) throws ValidatorException {
System.out.println("TestValidator.validate: " + value);
if (((String) value).equals("2")){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "TestValidator FEHLER", "TestValidator FEHLER"));
throw new ValidatorException(fm);
}
}

Resources