I am looking for some guidance/opinion on the best way forward to add field error highlighting in JSF 2.0. So far I have successfully implemented using Cagatay's example with a few minor adjustments to logic.
String styleClass = ( String ) uiInput.getAttributes().get("styleClass");
//Check the valid flag
if ( !uiInput.isValid() )
{
//Component already has a styleclass
if ( styleClass != null )
{
//check if it's already highlighted
if ( !styleClass.contains("ui-input-invalid") )
{
//if not add the error class to it
styleClass = styleClass + " ui-input-invalid";
//and put the new styleclass back on the component
uiInput.getAttributes().put("styleClass", styleClass);
}
} else
{
//no current style class so just add the error class
uiInput.getAttributes().put("styleClass", "ui-input-invalid");
}
} else //component is valid so we might need to remove a highlight
{
//component has a styleclass
if ( styleClass != null )
{
//check if it is already highlighted
if ( styleClass.contains("ui-input-invalid") )
{
//remove error class from the string
styleClass = styleClass.replace("ui-input-invalid", "");
//and put the new styleclass back on the component
uiInput.getAttributes().put("styleClass", styleClass);
}
}
}
I have also used the suggestion of adding el to each component's styleclass - styleClass="#{component.valid ? '' : 'ui-input-invalid'}".
Both methods work like a charm when used in conjunction with Bean Validation JSR303. However I also have 2 additional validation stages. 1 to validate the form as a whole i.e. correct combination of fields and 1 to validate our general business rules once the field and form validation is successful. In order for these stages to also add the highlighting I need to do some manual work. For both highlighting approaches I have to manually set the component(s) valid flag to false. To have access to the component I have bound it to its own object in the form vo. Now for Cagatay's example I need to add all of the components to a List and then pass this list to the highlighting method. If I use the styleclass approach I don't have to worry about a component list and passing to a highlighting method. This seems the better approach to me however I'm a little concerned that it is adding logic to the JSF page which is something I want to stay away from.
What do you feel is the best approach or is there another way I am not aware of? Also I assume there is no other way of setting the valid flags without binding to the component? At the moment I having to bind every component so I can set its valid flag.
It's been a while since I asked this and in the mean time we have actually partially implemented JSF into our enterprise app. The solution for the field highlighted was quite complicated and in order for it to work, be reusable and be customisable it really has to fit snuggly into a framework that encompasses JSF/Input Value Objects, associated Input Field objects and Bean Validation. Therefore someone stumbling here may not get the answer they are looking for. However I going to include an portion of our internal design docs which describes the mechanism. Hopefully this will help anyone else:
Field Highlighting and Error Messages Field highlighting in JSF
proved to be quite a complicated task. This is because the html
id/name is generated by jsf at runtime and can include many prefixes.
JSF will add a prefix to an id when it is inside a
form/tab/datatable/composite component. An id of ucn may end up
becoming tab1:contentForm:jsfDataTable:1:ucn. It is therefore
virtually impossible to try and predeterime what an id will be and
then to try and highlight. To resolve this issue a
preRenderComponentEventListener class is used. This is registered in
the facesConfig.xml along with an input type. This tells the JSF
lifecycle to run this class whenever that type of input is about to be
rendered. We then have access to the short and long ids of the input
which we can then save and look up later. The full procedure is as
follows:
Entry in facesConfig.xml registers a
preRenderComponentEventListener and the associated type of input.
Each time before the input is rendered the processEvent method is
called.
Entry in facesConfig.xml registers a HashMap called
componentMap which is used to store the input ids.
When the
processEvent method is called the Input element is retrieved. The
componentMap is retrieved and input’s id/clientID is added to the map.
The id of the input is the Key (this is the short id i.e. ucn) and the
ClientID is the value (this is the long JSF generated id i.e.
csn01Form:jsf454:ucn:1). To handle multiple inputs of the same name
like in DataTables the key is added with an Incrementing Index. E.g.
if ucn3 is already in the map ucn4 will then we added.
Once this
process is complete the componentMap will contain entries for every
input field. Therefore by using the short id the full clientID can be
retrieved.
In the BackingBean FormatValidationExceptions and
RuleExceptions are caught and handled.
FormatValidationExceptions. These derive from BeanValidation. A
subclass of an InputVO is created which contains subclasses of
Destin8Input (See CSN01InputVO). If format validation is needed on an
Input they should be annotated with a custom bean validation. E.g.
#StringCheck (See Bean Validation).
The FormatValidation class
has a method called validateFormats which takes in a type of InputVO
and runs it through the Bean Validator (when using a Transaction
Controller this method will automatically be run). The Bean Validator
will automatically take each annotated field and run the isValid()
method associated with the annotation. The #StringCheck for example
checks the value entered matches a regular expression and that the
number of characters entered is correct. Any failures will result in
a ConstraintViolation. At this point the error message is generated
using the Error Display Name from the Destin8Input. All validation
checks are performed and will result in a Set of ConstraintViolations.
In the validateFormats method the Set of ConstraintViolations is
looped round and each message is added to an Error Message List in the
ValidationFormatException. Each htmlID in error is also added to a
Field Error List.
The ValidationFormatException is caught in the
BackingBean. All Error messages are added as a FacesMessage to be
displayed at the top of the page.
RuleExceptions are similar
except messages and fields to highlight are manually added when
throwing an exception. The message code will be looked up from the
DB.
The List of ids in error is now looped round and is used to
retrieve the associated full ClientID from the componentMap. Each
ClientID is added to a List.
This List is passed to the
JSFUtils.highlightFields method where each ClientID is added to a ~
Delimited String.
This delimited String is then added to the
RequestMap with a key of ‘errors’ (this is a map automatically
available as per of each request).
This String is then retrieved
as part of the Destin8Template.xhtml -
A
javascript method called highlightFields in then immediately called.
This effectively loops through the delimited String, gets the full id
and then adds the Error css class using jQuery.
It is important to
note that the link between a Java Input and a JSF Input is the id. In
order to connect the 2 it is vital they have the same ID. This is
achieved by using the IDConstants class. This is an ENUM which
contains entries for different fields. An entry is also added to the
IDConstants managed bean which allows access via a facelet. This is
then added as the id attribute for the applicable input element.
Related
I am trying to create a contract between with a consumer when making a request for an item information. The item has a very complex data structure with nested properties and contains fields that ranges from strings, lists, arrays of strings, arrays of enums etc. There is also a complexity added where some of the fields may be returned as a null or populated with a value respective to its type.
What I would like to do is to create a pact response matcher that can be re-used for any item. At the moment, there are 120 items (each item is a separate API call with the item name in the query param of the request) that I could request information for and writing a pact matcher for each item is not feasible / maintainable.
E.g. Sample response cut down ( the actual response is over 60 lines):
return new PactDslJsonBody()
.object("metadata")
.stringValue("name", "item-1")
.integerType("index", 1)
.eachLike("contents")
.stringType("param", "content-param")
.stringType("value", "content-value")
.closeArray
.closeObject
The problem I have is that the field contents could also come back as null from the provider. What I am trying to achieve is whether I can within the same PactDslJsonBody have an OR condition or something similar which can check for the eachLike but also can accept that the field is null.
Contents field populated:
{
"metadata":{
"name":"item-1",
"index":1,
"contents":[
{
"param":"content-param",
"value":"content-value"
}
]
}
}
Contents field null:
{
"metadata":{
"name":"item-1",
"index":1,
"contents":null
}
}
I see there is PactDslJsonBody.or() available but the usage of this is not documented clearly, hence I am unsure if this is the intended usage for the above use case.
Writing separate tests is not feasible as this is a specific use case to repeat the same PactDslJsonBody for n number of consumer tests, one for each item. We need to test each item as we have a direct mapping of some field values as enums between the consumer and provider hence we want to make sure that each item has the expected values for such fields. We also dont know in advance which items will this field as null and which ones have it populated, hence why we wanted to have the option to use something like orNull etc.
I have looked quite a lot in the web and couldn't find a definitive answer to the above. Any help on this would be appreciated on how to move forward with this. We really want to use Pact since it is the go to tool for us and the above is a crucial use case for us to test.
I am using Pact JVM version 4.3.15 and using V3 specification.
Thanks.
See https://docs.pact.io/faq#why-is-there-no-support-for-specifying-optional-attributes. You need to write two separate test cases that cover both scenarios.
I have an OWL file (OWL2) that I need to parse and ultimately write the data into some file. The file contains AnnotationProperties, DataProperties, ObjectProperties and Classes.
My first aim is to try to list out the property information as much as possible. i.e. for AnnotationProperties to see if I can print out the name of the property and the "value".
Similarly, to be able to display the class details i.e. for each class, the name of the class, the properties i.e. data or object properties of the class. I'm not sure how to do this and any reading I've done so far is confusing because it seems to talk about instances, which I don't believe are present in the file. Also, the OWLAPI javadoc and documentation and such are not very helpful with the kind of methods I might have to be calling.
E.g. if I had the following AnnotationProperty:
<owl:AnnotationProperty rdf:about="&xxx;SOME_ID">
<ABC rdf:datatype="xsd;string">1235412</ABC>
</owl:AnnotationProperty>
ontology.getAnnotationPropertiesInSignature() would get me a set of AnnotationProperties and I can iterate and say property.getIRI().getFragment() to see the SOME_ID, but now how would I obtain and display the inner contents i.e. the ABC-1235412 ? Similarly, any help on how to obtain the information of a class i.e. display or show its properties and restrictions is appreciated.
The fragment you're showing does not create an annotation assertion axiom with property SOME_ID, it is instead an annotation on the property SOME_ID itself. The triple looks like this:
SOME_ID ABC "1235412"^^xsd:int
From your description of what you're trying to do, you /need/ instances - values for any property (annotation, object or data property) are expressed through assertions, i.e., axioms which refer to an individual (or instance - the two names refer to the same concept).
E.g.,
Ignazio hasAge "38"^^xsd:int
would be a data or annotation property assertion on the individual Ignazio with value 38.
To access these assertions, you can use
OWLIndividual ignazio = ...
ontology.getAnnotationAssertionAxioms(ignazio);
To access annotations like the one you show, i.e., on the annotatio property itself:
OWLAnnotationProperty some_id = ...
ontology.getAnnotationAssertionAxioms(some_id.getIRI());
I have to generate a report, that displays info about one object ( so the input is only one bean ).
The first problem is - this bean should contain lists of sub-beans( for example, comments, with comment type and comment date ). So I can pass them to a sub-report.
The second problem is - there is an array of 4 sub-beans, that contains few fields. I can create a separate field for each sub-bean's property ( firstSubBeanName, secondSubBeanName... ) , but it's ugly :(. Ideally, there should be a way to access these beans in a such way :
$F{test}[0].name
Please help.
If your list have a name (ie is a property of the object), you have just to pass as Data Source Expression for the subreport this property
$F{subBeansList}
The subreport should be ready to receive such kind of data. If you are using struts, it is possible you should use this class:
org.apache.struts2.views.jasperreports.ValueStackDataSource
as intermediary on your list field to be passed to the subreport.
The second question, the easy way is to use a list, so you can use this expression:
$F{test}.thelist.get(0)
I'm trying to make a set of custom tags that encapsulate form elements (markup and validation).
There's a method given to retrieve the "Out" object easily:
JspWriter out = getJspContext().getOut();
However I can't figure out how to get the request object. I want to be able to directly access the submitted form values from within the Tag class so that I can validate each field.
The documentation is quite sparse, so I thought maybe I could use the JspContext object to somehow get the request attributes. But I don't understand the different scopes.
System.out.println(getJspContext().findAttribute("field1"));
always prints "null".
Enumeration e = getJspContext().getAttributeNamesInScope(1);
Looping through and printing out the enumeration just gives me a list of classes that don't exist:
javax.servlet.jsp.jspOut
javax.servlet.jsp.jspPage
javax.servlet.jsp.jspSession
javax.servlet.jsp.jspApplication
javax.servlet.jsp.jspPageContext
javax.servlet.jsp.jspConfig
javax.servlet.jsp.jspResponse
javax.servlet.jsp.jspRequest
So is this even possible?
If not, could anyone point me to a tag library that deals with form display and validation? I searched the internet for a couple hours and it seemed every single one was discontinued and I couldn't download them. Either that or suggest a better alternative for handling forms.
Edit: The tags extend the SimpleTagSupport class.
If your class is extending TagSupport, you can access the protected pageContext variable. From that you're able to retrieve the request object.
http://java.sun.com/webservices/docs/1.5/api/javax/servlet/jsp/tagext/TagSupport.html#pageContext
I have a basic doubt in how to proceed in my application. I have a form and I need to validate that all the inputs which are numbers. I have a problem in deciding the type of the attributes of the bean asociated with the form. I don't know if setting them to String or to double and here are the reasons:
If I set them to double: If I enter in the input something which is not a number when spring populates the inputs into the bean I get an Exception in the JSP that it could not convert it into double.
If I set them to String: I have a good validation although I have to change them later to double. But my problem here is that this bean is stored in a database with hibernate and the annotation #column would store it as a text and I would like to store it as if it were a double. Is there any posibility to change the column type to the double deferred type?
Does anyone can give me any idea in how to preceed in this case?
Thanks.
I suggest you always work with your domain types and not use String just because that's the way HTTP sends params. If a field has type double, you will use it as such in your code and also store it as such in the database. Let Spring convert the request params to your needed type.
Data binding is useful for allowing user input to be dynamically bound to the domain model of an application (or whatever objects you use to process user input). Spring provides the so-called DataBinder class to do exactly that.
You can register those in the initBinder method of your controllers and will allow you to transform the Strings from your request into the desired type. See for example the CustomNumberEditor class used to parse user-entered number strings into Number properties of beans. You can then combine this with the Validator interface for more complex checks.
EDIT: Spring binding uses typeMismatch error codes for binding errors when a conversion fails (required code if you specify a field as required but you don’t supply it). In your case it defaults to showing the exception message. To change the message to a more friendly one, you must supply a bundle key in your property file using the typeMismatch prefix.
This is specified by the DataBinder.setMessageCodesResolver and defaults to org.springframework.validation.DefaultMessageCodesResolver. In the javadoc of DefaultMessageCodesResolver you can see complete examples, but basically, you just have to add an entry like this in your properties file:
typeMismatch.yourField=Your user friendly error message goes here
You can map the exception to the custom message if you have an entry in the following form in your message.properties (or the equivalent message bundle that you are using).
typeMismatch.fieldName, where fieldName would be the name of the field you are validating.
If you are using Spring 3.0
have a look at the Overriding Defaults with Annotations part of
Spring 3 Type Conversion and Validation
If you are using Spring 2.x+ you can achieve this by registering Custom PropertyEditor as mentioned in above post