aspose file tools*
The moose likes JSF and the fly likes Retrieving JSR 303 validation/constraints on UIInput Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "Retrieving JSR 303 validation/constraints on UIInput" Watch "Retrieving JSR 303 validation/constraints on UIInput" New topic
Author

Retrieving JSR 303 validation/constraints on UIInput

Joshua Hewitt
Greenhorn

Joined: Sep 28, 2007
Posts: 6
First a bit of background...

I want to implement a bit of simple client-side validation using JavaScript/jQuery. The way it works is looking for certain classNames on the form inputs such as min3, required...

Then I wanted to make this transparent to the programmer, so I extended the renderkit so for each component it looks at it's validators and injects these classNames:
@Override
public void writeAttribute(String name, Object value, String property) throws IOException {
Object newValue = value;
if (BKRenderKit.CLASS_NAME.equals(name)) {
UIComponent component = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
if (component instanceof UIInput) {
for (final Validator validator : ((UIInput)component).getValidators()) {
if (validator instanceof LengthValidator) {
final int min = ((LengthValidator)validator).getMinimum();
final int max = ((LengthValidator)validator).getMaximum();
if (min > 0) {
newValue = newValue + " min" + min;
}
if (max > 0) {
newValue = newValue + " max" + max;
}
//...
}
}
}
super.writeAttribute(name, newValue, property);
}

So far so good. However, we now want to move away from JSF validators and use JSR 303 validation on the beans (the idea is to reuse code for JSON REST interfaces).

Does anybody know if there is there any way to get a list of the JSR 303 validators off a UIInput?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

I'm not sure that the JSR303 spec can completely replace JSF validators, since what they're looking for is slightly different. In any event, a lot of my current stuff is taking its validation cues from ORM entity validity definitions, not the UI Model (backing bean) properties. So your approach is too narrow for what I've been doing.

I'm presuming that you are implementing HTML5 rendering, since HTML4 doesn't support min/max on inputtext controls.

To actually obtain the validation parameters, you'd need to introspect the bean that contains the annotated property. The problems with that (in addition to what I mentioned in my case earlier) is that the actual property value is defined as an EL value reference expression and the EL processor only knows the bean in question as a transitional stage to getting/setting the actual value. You could "brute-force" parse the EL value property of the UIComponent, but while "#{bean.property}" form is the most common syntax, there are a lot of nastier syntax variants that people have concocted. I spend a lot of time, in fact, trying to persuade them not to.


Customer surveys are for companies who didn't pay proper attention to begin with.
Joshua Hewitt
Greenhorn

Joined: Sep 28, 2007
Posts: 6
There seemed to be a decent match between them and JSR303, plus I can create my own Constraint/ConstraintValidators for anything they might chuck at me. Even the JSF valitators probably weren't going to be enough.

So you are putting UI validation based on annotations on your JPA (or similar) entities? Sounds like the way to go. But we will probably have DTOs in the way (though I guess something could be done about that), plus legacy code which doesn't use ORM.

Right now I'm on plain 'ol HTML4/XHTML1. The final output shoves all the "configuration" into the input's class: input tyle="text" class="min4 max8 required". May move onto HTML5 but I'm pretty new at this - only just started to muck around with the renderkit a few days ago and saw it as a good way to get HTML5 support.

Ouch, introspection sounds nasty. In our case it might be #{bean.property} or #{bean.dto.property}, though as you say you never know what a developer can concoct.

...and then I have to work out a transparent way to execute the validation for JAX-RS requests...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

I'm using the RIchFaces ajax:validate elements to apply validations on the "onblur" events. They hook into both the ORM validation annotations and the JSF validations, which means that they handle things like the "required="true"" UI constraint as well.

Using validation constraints to alter the UI can be a little dangerous - you can end up with a redesigned screen layout without intending to. Although if I was to go that route, I'd probably attach a support class to the backing bean that could be used to do everything in a more POJO-like way. Something like:




Where the ConstraintSnooper would do the reflection from the indicate bean and property.

Although that points out to me that SSN is a discrete data type, despite not having a distinct type identity (class) and I normally would simply have defined an ordinary CSS "ssn" style that the app would reference globally instead of building up from primitive sub-CSS.

DTOs, are, of course obsolete, but you should be able to annotate them with validators.
Joshua Hewitt
Greenhorn

Joined: Sep 28, 2007
Posts: 6
I'm trying to avoid programmers having to think about putting the styleClass on the tag, which is why right now I hook it in a RenderKitWrapper. I'm still in experimental mode, if it gets too hairy it may all get chucked in favour of using Prime/Ice/Rich faces instead (though I'm worried about accessibility in those frameworks - we have a legal obligation to be AA).

Flying wildly off-topic now ;-) DTOs are also controversial amongst us (and I'm sure the source of much heated debate in various posts in this forum). It looks like we will need them for the legacy back-end, and for the new stuff we'll use the JPA entities as DTOs. Though there may be a need for DTOs as a sort of fa├žade to various JPAs in less CRUD-like situations. Will have a ganders to see what others are doing...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

Actually, one of the primary ideas behind JSF is that Sun expected the UI parts to be implemented by someone with graphic design talents and the business logic (backing bean) parts to be implemented by someone with programming talents. The fools! We all know that in our Brave New World, one person is going to have to do it all on unpaid overtime.

Anyway, snark notwithstanding, it's not unreasonable to have the UI designer deal in terms of UI components, and that means that it's more logical to have that person specify UI styles (CSS) than to have the business logic force them on the UI.

Regarding DTOs, the original reason for DTOs was that in EJB1 and EJB2, the EJBs were special objects that could only be dealt with in a limited environment. In order to keep the UI and abstract business logic independent of EJB, you had to stage your data via a DAO using a DTO. In EJB3/JPA, the concept of detached POJO objects was introduced, and these objects serve as their own DTOs. That is why DTOs are now obsolete: they're redundant.

My current persistence architecture is built to support the idea that everything about the persistence tier is working with detached objects (a lot of people cheat and keep them attached all the way up, but that's sloppy, IMHO). I have 3 persistence layers:

1. The service layer. Has persistence-dependent business logic, including managing the relationships between multiple persistent entities
2. The DAO layer. Has the basic CRUD/Finder functions for a single entity type or parent/child types (essential a Session EJB).
3. The Entity objects themselves.

The transactional boundary is always located at the entry/exit of the service layer, and that's where objects get detached. So some of my finders return not only simple objects, but graphs of objects required to make the detached working set for the higher-level operation that requested them.
Joshua Hewitt
Greenhorn

Joined: Sep 28, 2007
Posts: 6
Tell me about it ;-)

But I'm not invading UI territory (well, not too much). I see class simply as a marker, be it to apply styles or anything else ("cofiguration" for validation in this case). Obviously the way to go is to make use of HTML5 form input attributes, and data-* attributes for things it may not cover, but I don't see adding classes as too invasive. UI designers can still use styling classes like "pinkBackgroundWithFloweryBorder" on an input, and JSF will just add a "required" or "email" to the list of classes (still leaving the original styling classes). The only class the back-end adds that changes style is "error" (red text etc). But as I am also designing the UI architecture I have notified myself ;-)

I'll see what I can do about avoiding DTOs (poor guys, so hated when all they are is simple beans with just getters & setters), but there will be cases where we don't have a managedBean or a JPA entity, and I have to chuck data around somehow. I take it that JSR 303 validations on a "proper" buisiness EJB is a no-no.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

Mostly, CSS classes ARE just used for UI management. That's what they were designed, for after all. In fact, the muddling between display and semantics in straight HTML was the primary impetus for creating CSS to begin with.

You most definitely CAN annotate EJB3 entity EJBs for validation. I'm pretty sure that that was part of the design considerations for EJB3, and certainly hibernate validation supports entity validation annotations.

I'm less certain on EJB2 and EJB1 with remote interfaces, but in theory it's possible. Or, to be precise you can annotate them, but I'm not sure about getting the annotations recognized and applied.
Joshua Hewitt
Greenhorn

Joined: Sep 28, 2007
Posts: 6
I realise that classes are mostly for styles (which I guess is the reason why, as class is a reserved name, in frameworks they end up being called styleClass), but the HTML4 specification says they serve another purpose, "For general purpose processing by user agents". In Microformats, for example, class names are used to add semantics. I see no reason why it is wrong to use class names to mark validation rules. Unless of course there is a better alternative (such as the mechanisms provided by HTML5 - which we will be migrating to sooner rather than later I hope).

I know you can add JSR303 validation tags to EJBs, but doesn't it feel wrong for EJBs containing business logic? I'm not sure about that, it's just a gut feeling. Will look up a bit more on the matter.

Back to the original topic ;-) I've just seen what you were talking about getting the value ValueExpression, something like component.getValueExpression("value") and start messing around from there, no? If I work out something useful I'll post it...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16065
    
  21

I think that the renaming of the HTML "class=" attribute to styleClass was probably because "class" is a reserved word in Java, although it's not obvious why that should matter in VTL. Maybe they had considered other types of (non-style) classes for the VTL elements as well. I wasn't paying attention at the time.

The main reason I am wary about using CSS classes for non-UI purposes is that it borders on mixing business logic into the View definition, and that's a practice that I don't encourage. MVC works best when the logic and the UI remain as separate as possible.

Value validation on EJBs is not an issue. I use it as a first-line defense against accidentally setting values that would throw an exception at commit time, as for example, when the database column is limited to 5 characters long, but the java.lang.String property of the EJB has no such restriction. Or you want to ensure that it isn't set to NULL.

Business logic validation is another matter, but I don't use validators for that, since my persistence service methods do the sanity-checking anyhow. The only case where I'd put a business-logic validation on an EJB would be in cases where the actual database table had a trigger that might throw an exception. Ideally, EJBs are general-purpose reusable objects, and so putting arbitrary business-based limits on them is something I'd prefer to offload to higher levels.
 
Don't get me started about those stupid light bulbs.
 
subject: Retrieving JSR 303 validation/constraints on UIInput