I'm trying to evaluate GWT validation library with a very simple example taken from the author site.
and here is a code snippet
validator.addValidators( "birthYear",new IntegerValidator(schoolName_txt, 1890, 2009)
.addActionForFailure(new StyleAction("validationFailedBorder"))
.addActionForFailure(new LabelTextAction(error_label))
);
but the problem is that when I run the application I got the following error:
no property localization given for key: birthYear
but I'm sure that I have included this key in my localization files,so what is this?
Thanks
To get rid of this error message you have to extend ValidationMessages:
import eu.maydu.gwt.validation.client.i18n.ValidationMessages;
public class CustomValidationMessages extends ValidationMessages {
#Override
public String getPropertyName(String propertyName) {
return propertyName; // This just returns the property name instead of the error message
}
}
Then change pass an instance of this class to the ValidationProcessor instance instead of just an empty parameter:
ValidationProcessor validator = new DefaultValidationProcessor(new CustomValidationMessages());
The purpose of this I suppose to give you a chance to change the displayed input name in the error message if your app is multi-language.
Related
I've got a simple class which get's validated using the boolean isValid() method, which works and of course the error message is at class/type level.
Here's my simple class:
public class NewPasswordDTO {
#NotNull
public String password;
#NotNull
public String confirmation;
#AssertTrue(message="Passwords must match.")
protected boolean isValid() {
return password.equals(confirmation);
}
}
But what I really want is something like that:
public class NewPasswordDTO {
#NotNull
#Equals("confirmation", message="...")
public String password;
#NotNull
public String confirmation;
}
So the error message would be set at field level and not at class/type level.
Is this possible somehow? Maybe using a custom Validator for that class?
Thanks in advance!
SOLUTION:
Thanks to Gunnar! I've just came up with a nice, universal solution :-). I simply used (means copy & paste) the code from Hibernates #ScriptAssert and ScriptAssertValidator and modified it slightly:
#ScriptAssert:
Add new String field(). (this is where the error message gets appended)
ScriptAssertValidator:
Inside the initialize method, make sure to also save the fieldName and message properties, because we need to access them in the next step
Add this snippet at the bottom of isValid method:
context.buildConstraintViolationWithTemplate(errorMessage)
.addPropertyNode(fieldName).addConstraintViolation();
Also add context.disableDefaultConstraintViolation(); somewhere inside the isValid method to not generate the default error message which else would get appended at class level.
And that's it. Now I can use it like that:
#FieldScriptAssert(lang="javascript", script="_this.password.equals(_this.confirmation)", field="password", message="...")
public class NewPasswordDTO { ... }
You either could use the #ScriptAssert constraint on the class (note that a constraint should always be side-effect free, so it's not a good idea to alter the state of the validated bean; instead you should just check whether the two fieldss match) or you implement a custom class-level constraint.
The latter also allows to point to a custom property path for the constraint violation, which it allows to mark the "confirmation" property as erroneous instead of the complete class.
Simple answer : It is not (unless you implement it) :http://docs.oracle.com/javaee/6/api/javax/validation/constraints/package-summary.html shows all annotation constraints.
Of course you could inject your string as a resource in your class by #producer and so on (which recently is discussed to be removed in jdk8), but you could not use this value for your assert. In reply to the comment:
This was asuming that the nature is a constant string which you would like to use as a string resource.And then of course it is possible to write your own class based on java.lang.string with a #Producer which is then #Inject - able. Though it is certainly not the way I personally would deal with constant strings.
If you’re using the Spring Framework, then as an alternative to the #ScriptAssert using a JSR 223 scripting, you can use the #SpELAssert that uses the Spring Expression Language (SpEL). The advantage is that it doesn’t need any JSR 223 compliant scripting engine which may not be available on some environments. See this answer for more information.
How can I create my own user class with additional properties in it?
I tried to create my own user class by implementing org.owasp.esapi.User interface and added some extra properties.
public class MyUserClass implements User{
then I tried this
MyUserClass userClass=(MyUserClass) ESAPI.authenticator().getCurrentUser();
But getting this exception:
SecurityConfiguration for Logger.LogEncodingRequired not found in ESAPI.properties. Using default: false
java.lang.ClassCastException: org.owasp.esapi.reference.DefaultUser cannot be cast to com.bean.MyUserClass
I also tried to extend DefaultUser class but error was same.
The "exception" you are posting is actually two different items: (1) a log message, and (2) an actual exception. And while these are different items altogether, they still stem from the same underlying issue.
Short answer: You are forgetting to set your security configuration system property when your app initializes. It should look something like this:
System.setProperty("org.owasp.esapi.SecurityConfiguration",
"org.you.yourapp.YourAppSecurityConfiguration");
Where org.you.yourapp.YourAppSecurityConfiguration is the name of a class you'll write that implements SecurityConfiguration. Because you are failing to set this system property, when the following ESAPI code runs:
private static String securityConfigurationImplName =
System.getProperty("org.owasp.esapi.SecurityConfiguration",
"org.owasp.esapi.reference.DefaultSecurityConfiguration");
...then since you never set the property, ESAPI is selecting the DefaultSecurityConfiguration for you.
When this DefaultSecurityConfiguration goes to initialize ESAPI's internal logging system, the following method is called:
protected String getESAPIProperty( String key, String def ) {
String value = properties.getProperty(key);
if ( value == null ) {
logSpecial( "SecurityConfiguration for " + key + " not found in ESAPI.properties. Using default: " + def, null );
return def;
}
return value;
}
The property it's looking for here is a boolean called Logger.LogEncodingRequired. So if you want this first message to go away, you need something like:
boolean logEncodingRequired = true; // or false, your choice
System.setProperty("Logger.LogEncodingRequired", logEncodingRequired);
That takes care of your first issue:
SecurityConfiguration for Logger.LogEncodingRequired not found in ESAPI.properties. Using default: false
Your second issue is also a result of ESAPI choosing a DefaultSecurityConfiguration for you. This default configuration has an authenticator() method that returns an instance of FileBasedAuthenticator. And as that javadoc link explains, you need to have a users.txt file on your runtime classpath that contains all the serialized information about your users. And, of course, the FileBasedAuthenticator returns instances of DefaultUser which is why you're getting the 2nd issue (which is an actual exception):
java.lang.ClassCastException: org.owasp.esapi.reference.DefaultUser cannot be cast to com.bean.MyUserClass.
Because you can't cast the DefaultUser (passed back from the FileBasedAuthenticator) to your own MyUser class.
Confused? It's really not so bad. Just implement your own SecurityConfiguration and set it as a system property, and you will be all set. HTH.
Sorry I am new to Spring and Java and this may be covered lots of times but I wanted to get some advice.
I'm creating a Spring web application which needs to retrieve user data from an existing REST based XML web service. I am going to create a domain object, service and DAO which uses the Spring REST template to invoke the web service.
In the DAO I was going to create a method like this:
public User getUser(String userId)
If there is a problem (for example if the user account is locked or been deleted), the web service returns a 200 response and puts an error code in the XML response. These errors should be displayed in the application and I will need to be able to identify the error so I can show custom error message to the user. What is the recommended way to handle these error, should I:
Define different exceptions (runtime) for each of the error response codes and add these to the method signature
Use a single exception (e.g. UserException) and use different messages.
Do something else
Any help would be highly appreciated.
You want to use different exception for each error type by extending Extension. if you have many different ones, try to group them using class inheritance. An example would make it simpler. Suppose you have these 2 kinds of errors, account deleted and account locked, you would do :
class AccountException
extends Exception {
}
then you extend Account extension for all the errors involving account problems, eg:
class AccountLockedException
extends AccountException {
}
and
class AccountDeletedException
extends AccountException {
}
etc... This way you make it crystal clear and don't have to look through all your exceptions. Not sure I'm clear enough, It's my first answer here. GL!
I would create a single Exception class for a category. For instance, for all user related exceptions, you can create something like below:
This way, it will be clean to catch one exception and verify the error code to find what caused the exception.
public class MyException extends Exception{
public static final int ERR_USER_NOT_FOUND = 101;
public static final int ERR_DB_ACCESS_ERR = 500;
private int errorCode;
public MyException(int errCode){
this.errorCode = errCode;
}
public int getErrorCode() {
return errorCode;
}
}
I'm just learning how the Play 2.0 framework. So I have a quite basic question: I just want to take a URL parameter and display it in the view. How do you do that?
I created the URL pattern:
GET /test/:id controllers.Application.testOutput(id: Long)
And an apporoptiate methode in Application:
public static Result testOutput(long id) {
return ok(
views.html.test.render(id)
);
}
How do I call the id variable form the view? I know how to call methodes defined in the model in the view, but I don't know how to display the id variable in the view. Is it the right way to pass the id variable to the render methode?
I'd like to understand the underlying concept, so an detailed explanation to the answer would be great!
Our test URL will be http://localhost:9000/greeter?message=hello and this will output a text/plain response with the content of the parameter message (ie hello). First, let's define the route
GET /greeter controllers.Greeter.say(message: String)
Then, create a Greeter controller (I use Java)
package controllers;
import play.*;
import play.mvc.*;
// This lets you call the template without the views.html prefix
// import views.html.*;
import views.txt.*;
public class Greeter extends Controller {
public static Result say(String message) {
return ok(greeter.render(message));
}
}
You can see that ok() calls a scala function defined in the file app/views/greeter.scala.txt Here is the content of that file (the first line defines the message parameter of type String used inside the function
#(message: String)
I'm the content. Note that you can place
anything you want here. Scala expressions
begin with the '##' character. For example
next line contains the content of message:
#message
In this case I used .txt for file extensions because I wanted plain text response. If you want to produce HTML output, simply make a .scala.html file
The client request is handled by the Play router, which in turn forwards it to some action (which is a method inside a Controller)
GET /greeter Greeter.say
From the Play doc
The last part of a route definition is the Java call. This part is
defined by the fully-qualified name of an action method. The action
method must be a public static void method of a Controller class. A
Controller class must be defined in the controllers package and must
be a subclass of play.mvc.Controller.
You can add a Java package before the Controller class name if it
isn’t defined directly under the controllers package. The controllers
package itself is implicit, so you don’t need to specify it
Inside the action, you can get the parameters via the param object or directly by the method signature:
public static void say(String what) {
...
}
and you can pass objects to the template via render(what) like you do in your sample.
Finally your template can access those object with the ${what} syntax.
EDIT This is the Play 1.x way of doing things. I didn't notice your tag, but still hope this helps. Play2 uses the new Scala template engine, here is the guide. It seems you must declare your parameters at the beginning of the template, then you can access them via the #what syntax. That's because the template is now a compiled Scala function, so it can do type checking at compile time and things like this. You pass parameters to this function with render(what) (like you do) . I personally don't use Play2.0 myself: it's a big improvement from the technical point of view, at the cost of being less intuitive and more verbose. I don't think that simpler projects benefit from these improvements
In Play 2 templates are just plain functions, so you can call them as you would call any function.
I have an interface that extends the com.google.gwt.i18n.client.Messages class, which I use for retrieving i18n messages in my GWT application. It looks like this:
public interface MyMessages extends com.google.gwt.i18n.client.Messages {
#DefaultMessage("Hello world")
#Key("message1")
String message1();
#DefaultMessage("Hello again")
#Key("message2")
String message2();
//...
}
Normally, I create an instance of it using GWT.create() like so:
private MyMessages messages = GWT.create(MyMessages.class);
However, this does not work with server-side code, only client-side code (it throws an error saying that GWT.create() is only usable in client-side code).
The answer to a similar question points to a separate library that you can download which will let you access the i18n messages on the server, but I don't want to download any extra libraries (this seems like a simple problem, there must be a simple solution).
In summary: How can I access my i18n messages in server-side code? Thanks.
On the server side you can use the standard Java localization tools like ResourceBundle.
Look here for a tutorial how to use it.
// Create a ResourceBundle out of your property files
ResourceBundle labels =
ResourceBundle.getBundle("LabelsBundle", currentLocale);
// Get localized value
String value = labels.getString(key);
The GWT specific way of creating an interface out of your property files and providing implementations via deferred binding can not be used on sever side Java.
If you are fearless and willing to spend the time, you can implement a code generation step to read your property files and generate implementation classes for your message interface. That's exactly what the Google GWT compiler does behind the scene.
I agree with Michael.. I was having this problem of trying to "localize" messages generated on the server.... but I decided to instead just throw an Exception on the server (because it is an error message which should only happen exceptionally) which contains the message code, which the client code can then look up and show the correct localized message to the user.
There's a great library for GWT internationalization gwt-dmesg. It allows you to 'share' .properties files between clent and server. However, project looks to be abandoned by author and you must recompile it manually for use with GWT versio >= 2.1.0.
GWT.create() can only be used in client-side code.
The good thing to do is that you provide your own I18NProvider class/interface, from which then you can extend to server side I18N factory and client side I18N factory read the same resource bundle.
After that you can simply use it all over your system, unify your code.
Hope that helps.
Following vanje's answer, and considering the encoding used for the properties files (which can be troublesome as ResourceBundle uses by default "ISO-8859-1", here is the solution I came up with:
import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.ResourceBundle;
public class MyResourceBundle {
// feature variables
private ResourceBundle bundle;
private String fileEncoding;
public MyResourceBundle(Locale locale, String fileEncoding){
this.bundle = ResourceBundle.getBundle("com.app.Bundle", locale);
this.fileEncoding = fileEncoding;
}
public MyResourceBundle(Locale locale){
this(locale, "UTF-8");
}
public String getString(String key){
String value = bundle.getString(key);
try {
return new String(value.getBytes("ISO-8859-1"), fileEncoding);
} catch (UnsupportedEncodingException e) {
return value;
}
}
}
The way to use this would be very similar than the regular ResourceBundle usage:
private MyResourceBundle labels = new MyResourceBundle("es", "UTF-8");
String label = labels.getString(key)
Or you can use the alternate constructor which uses UTF-8 by default:
private MyResourceBundle labels = new MyResourceBundle("es");