java design problem for validations - java

I have the following requirement:
I have a validation system. One of the things that I need to do is perform validations on XML files, meaning validating that tag X equals a given value. I have more than one possible scenario, and in each scenario there is a different set of tags that need to be validated.
I don't want to repeat same code when testing same tags in different scenarios.
I'm trying to figure out a design that will solve this issue.
Any ideas?
Thanks.

I'd define pairs of XPath expressions and expected results for the scenarios.
The validator then would take a scenario (object), compile and apply the associated expressions to the xml document. This would select an element and the validator would check, if the element's content matches the expected value.

Erm, delegate to a shared method? Like:
void validateAppleScenario(Xml xml) {
validateFruit(xml);
// validate apples specific tags
}
void validateBanana(Xml xml) {
validateFruit(xml);
// validate banana specific tags
}
void validateFruit(Xml xml) {
// validate tags common to all fruit
}
Or if you prefer validators to be seperate objects, you can use subtyping:
interface Validator {
void validate(Xml xml);
}
class FruitValidator implements Validator {
void validate(Xml xml) {
// validate tags common to all fruit
}
}
class AppleValidator extends FruitValidator {
void validate(Xml xml) {
super.validate(xml);
// validate tags specific to apples
}
}

One approach would be to parse the XML into an object and then validate it in accordance with Bean Validation spec (JSR 303). Hibernate Validator is the reference implementation.* You can annotate your properties with validation constraints, and then specify validation groups so that certain fields get validated in certain scenarios.
There is more info here and here.
*Hibernate Validator is different from Hibernate ORM. They're only related in that Hibernate ORM uses Validator for its constraint checking.

Related

Endpoint Validation(#Valid, #Pattern, etc) with Optional

We have a need to have certain objects be wrapped in an optional because we need to know three states:
Missing (not present)
Null (present but null)
Data (present with data)
Currently we are wrapping these fields with Optional because spring rest endpoint will give us these states as null, Optional.empty() and Optional.of(value).
However, it does not appear that the validations are working. Do I need to do something different than just add #Valid, #Pattern, #NotNull, etc??
Note: there is a more detail breakdown of the need in this question (Java Spring (Jackson) Annotation for Not Present, Present but Null, and Present with Value)
Add javax.validation dependency
Below are the 3 steps to add validation.
Add #NonNull on the data member in the POJO class
class Employee
{
#NonNull
String name;
}
Create following method
private void validate(Employee emp){
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Employee>> violations = validator.validate(emp)
for(ConstraintViolation<Employee> violation: violations) {
//Your action. May be throw exception
}
}
Add #Valid where the object is used and invoke the validate method
void method(#Valid Employee emp){
validate(emp);
}
So the best solution that I found was to use Jakarta validations instead of Javax because the Jakarta will look into the optional field and apply the validation annotations.

Duplicate Tag accepted by JAXB

In our application, User is sending an XML like below:
<Decl>
<MessageHeader>
<A>Info</A>
<B>Info2</B>
</MessageHeader>
</Decl>
and using JABX unmarshller we are populating the java object.
But the problem is customer is asking to generate the error when he/she
send the message like below:
<Decl>
<MessageHeader>
<A>Info</A>
<B>Info2</B>
</MessageHeader>
<MessageHeader>
<A>Info3</A>
<B>Info4</B>
</MessageHeader>
</Decl>
JAXB is successfully unmarshling the xml and populating the object with second MessageHeader Object. Please note MessageHeader is not List type.
Is there any way to stop JAXB to behave like this and it should throw ParsingException. We cannot use schema validation of xml before parsing due to some reason. But is there any way that we can instruct JAXB parser to check target type is list or not and throw the error.
Thanks a lot in advance.
JAXB is a technology for generating Java classes for an XML Schema model. Therefore, any validation that JAXB performs is going to use XML Schema validation.
Is there any way to stop JAXB to behave like this and it should throw ParsingException
No. Not unless you enable schema validation in your JAXB unmarshaller.
We cannot use schema validation of xml before parsing due to some reason.
You should either supply the reason, or not mention it. It's a very strange rule, given that JAXB is an XML Schema technology and Java has native support for XSD validation.
Please note MessageHeader is not List type.
A List type is for simple types. MessageHeader is based on a complex type.
I recommend that you ignore the rule that says 'no schema validation'. Set maxOccurs=1 on MessageHeader and enable schema validation on the JAXB unmarshaller.
As already pointed out, the way to go is to use schema validation. Generate a schema and set maxOccurs="1" on MessageHeader. You can set the schema with:
unmarshaller.setSchema(schema);
If for some strange reason you absolutely cannot use schema validation you could do an ugly hack to throw an exception when a duplicated MessageHeader is processed with an implementation of Unmarshaller.Listener
unmarshaller.setListener(new Unmarshaller.Listener() {
boolean messageHeaderAlreadyPresent = false;
#Override
public void beforeUnmarshal(Object target, Object parent) {
// When <Decl> is encountered, set to false
if (target instanceof Decl) {
messageHeaderAlreadyPresent = false;
} else if (target instanceof MessageHeader) {
if (messageHeaderAlreadyPresent) {
throw new RuntimeException("duplicate MessageHeader");
}
messageHeaderAlreadyPresent = true;
}
}
});
Although this should work, I insist that you should reconsider schema validation.
Also note that the unmarshaller silently ignores some events, for example when encounters en element that is not mapped. That's not your case, because there is no mapping problem in your use case, but, for example if you received the message:
<Decl>
<MessageHeader>
<A>Info1</A>
<C>Info3</C>
</MessageHeader>
</Decl>
with element <C> instead of <B>, you would end up with values A = Info1 and B = null, as JAXB would silently ignore the element <C>.
You can capture these events and throw an exception setting a ValidationEventHandler to return false
unmarshaller.setEventHandler(new ValidationEventHandler() {
#Override
public boolean handleEvent(ValidationEvent event) {
// log event ....
return false;
}
});

Java validation of JSON payload: return errors as a tree

I have a webapp (Play framework 2.x, Java) that receives JSON payloads as input.
I have input payloads in different shapes like:
{
files: [{id: 1,name: null}}
requiredAttribute: null,
}
I want to output errors in this form, similar to the input:
{
files: [{name: "name can't be null"}}
requiredAttribute: "requiredAttribute can't be null",
}
I'd like to know how I can output errors in this form with Java without too much pain.
I know I'll loose the ability to output multiple errors per field and I'm fine with that.
I'm ok using any external library as long as it's easy to declare the constraints on the fields, so using something like Java validation and validation constraints annotations would be nice. But I wasn't able to find any support for this kind of stuff so far. Any idea how it could be done with Play or Java validation or Jackson?
Using bean validation, you can achieve this by calling validate() yourself and processing a collection of Set<ConstraintViolation<T>>.
You first need to get a Validator object. There may be ways to do this better, but one way is to use the factory (used this in the past, it worked with a Hibernate validator dependency on the class path):
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Then use the validator to retrieve a set of constraint violations (Assuming a generic type T for a bean class with the relevant constraint annotations):
Set<ConstraintViolation<T>> constraintViolations = validator.validate(myBean);
Map<String, String> fieldErrors = new HashMap<>();
for (ConstraintViolation<T> violation : constraintViolations) {
String message = violation.getMessage();
String field = violation.getPropertyPath().toString();
fieldErrors.put(field, message);
}
Note that for nested bean classes, you'll get a dot-separated "path" for field names.

Java - Custom/standard validation with Annotations

I'm using annotations in a project. The thing is i'm making custom validation that (partly) depends on annotations. I'm also making own annotations, but I want to use as much as I can from the JSR 303 standard.
to check if a field 'passes' the annotation constraints i've written some methods. Example:
static boolean isNotNullValid(Field f){
boolean valid = true;
if(f.isAnnotationPresent(NotNull.class)){
Object o = ObjectGetter.getFieldValue(f);
if(o==null){
valid = false;
}
}
return valid;
}
It's quite a lot of work to do this type of validation for all annotations. Is there some method i'm missing, like .isValid() ? I mean, of course, for the standard annotations.
Thanks in advance
You're not supposed to code that by yourself. You should instead rely on an implementation of the JSR, for example Hibernate Validator. The Validator it implements allows getting a set of constraint violations based on the annotations on the bean.

Struts 2 Conditional Annotation Validation without XML

I have a form with several fields (i.e. a,b,c,d,...) and the project I am currently doing right now is using Annotations for form validation in Struts2. XML usage is being discouraged.
I need to check a certain condition before I will validate form elements b, c, and d.
I was able to do the following:
#Validations {
requiredStrings = {
#RequiredStringValidator(...),
#RequiredStringValidator(...),
}
}
public String doSomething(){
...
return SUCCESS;
}
Is there a way to do this in Struts2 Annotation alone? Most similar questions I have found in SO all tell me to use XML method. Thanks.
Use an expression validator, or write a custom validator.

Categories