I have a domain object with size validation on two fields. The object is basically something like:
class foo {
String name
String description
static constraints = {
name nullable: false, blank: false, size: 3..31, validator { val, obj ->
// additional data validation returning a code if it fails
}
description nullable: true, size: 3..255
}
}
The problem is that I expect the "default" error to be of the form class.field.error (com.Foo.description.size.toosmall, for example) but in reality, when the domain class generates the list of codes, the final code is "size.toosmall", not the fully qualified version. So getCode is not very useful.
How is the list of codes generated and what is the best way to resolve this issue? I thought about iterating all the codes and using messageSource to look them up but this seems pretty crazy and extreme. And what baffles me is that I've never seen this issue before... making me think that somehow, something different is happening to cause the strange order of the codes. Or am I completely misunderstanding how it should work?
Alright... figured out that instead of iterating over allErrors and trying to extract the codes THAT way, you can instead iterate over fieldErrors and pass the entire fieldError into messageSource and it will self resolve.
So...
domainObject.errors.fieldErrors.each {
someList << messageSource.getMessage(it, locale)
}
Hope this helps someone else in the future.
Related
I'm wondering what would be the best way to ignore/discard the unknown enum values in GraphQL/Apollo server.
Let's say my GraphQL schema defines array of enums "enum Service { Supermarket, TicketSales }" and it works fine now, but later on other service I'm using is adding some new values (e.g. Playground) and my client just doesn't support it and I would just like to ignore it and return the supported values without error.
What would be the best way to do this in GraphQL. My first idea was to make directive that would read the supported values from schema and ignore everything else, but after googling around I didn't find any good examples how to do it. Can you point me a direction where to go about this?
If your resolver function will accept arbitrary strings, then you can use a custom scalar type, or just String.
"""
The type of a service. `Supermarket` means..., and
`TicketSales` means...; any other value is ignored.
"""
scalar Service
GraphQL generally places responsibility on the client to conform to the server's expectations, rather than making the server try to support any request. There are a couple of places you can reasonably expect an enum value like this to appear:
enum Service { Supermarket, TicketSales }
type Query {
inAReturnValue: Service!
asAQueryParam(service: Service!): Node
}
type Mutation {
asAMutationInput(service: Service!): Node
}
In particular it may not make sense to tell the server "make the type of this object be a playground" if the server just doesn't understand that. Conversely, if the server knows about "playground", it could return it in cases the client may not expect. Having an enum here makes it explicit what the server knows about. The server has said what it supports and it's the client's responsibility to cooperate.
Note that it's possible for the client to find out if the server supports playgrounds, if it's an enum value, and this might help it inform its behavior.
query GetServiceTypes {
__type(name: "Service") {
enumValues { name }
}
}
After playing around I found something that I can use to get around my original problem, so I will post it here in case somebody else is wondering the same thing.
So my original problem was in short that I'm receiving several different "available services" kind of string arrays from another services and I was thinking to map them to enum for better typescript support etc. But the problem was that if I get some unknown value from another service, my graphql will fail.
So my original idea was to fix it with directive which I after all got working:
# In schema
directive #mapUnknownTo(value: String) on ENUM
enum SomeAttribute #mapUnknownTo(value: "__UNKNOWN__") {
SomeAttribute1
AnotherAttribute
SomethingElse
__UNKNOWN__
}
And the directive implementation is:
import { SchemaDirectiveVisitor } from 'graphql-tools';
import { GraphQLEnumType } from 'graphql';
export class MapUnknownToDirective extends SchemaDirectiveVisitor {
visitEnum(type: GraphQLEnumType) {
const { value = '__UNKNOWN__' } = this.args;
const valueMap = type.getValues().reduce((map, v) => map.set(v.value, v.name), new Map<string, string>());
type.serialize = (v: string): string => valueMap.get(v) || value;
}
}
So this will map all the values not defined in schema into some custom value, which is not exactly what I originally wanted, but at least it's not giving an error, so it's okay-ish.
I'm still not 100% sure if directives are way to go on cases like this, but at least it's one possible solution.
I am writing some validation code and am not sure how to pass validation messages back to the calling code.
Exceptions come to mind, but I think that Exceptions should not be used in user input validation. As #Blowdart puts it:
Exceptions are not
control flow mechanisms. Users often get passwords wrong, it's not an
exceptional case. Exceptions should be a truly rare thing,
UserHasDiedAtKeyboard type situations.
From: https://stackoverflow.com/a/77175/125938. I'm extending that sentiment to all "incorrect" user input that a user might enter.
So the question is what to use instead of Exceptions. For certain situations, I could just use an IsValid… method that returns a bool for validity, but what if I want to pass an error message back with it? Should I create a custom "ValidationError" object, with a Message property? What makes sense and causes Least Astonishment (preferably a tried and tested pattern)?
If I were to do this in a truly object-oriented way, I'd adhere to the separation of concerns principle and compose a chain of classes that each deal with a separate step on the input - validation - output journey.
Let's say we are parsing a date from string as entered by the user.
My first class would encapsulate the raw value and attempt to parse the date (pseudo-code):
class TextualDate {
public TextualDate(string value) {
// just initialize with the provided value
}
public Option<Date> AsDate() {
// try parsing and either return the date or not
// the Option<Date> type is here to suggest that the conversion might not succeed
}
}
Next I'd have a validation class that instantiates the TextualDate class, invokes its AsDate() method and returns the validation result:
class ValidatedDate {
public ValidatedDate(TextualDate value) {
// initialize with the provided value
_textualDate = value;
}
private TextualDate _textualDate;
public ValidationResult Validated {
var maybeDate = _textualDate.AsDate();
// see whether we have a date or not
return new ValidationResult(...);
}
}
In our ValidationResult class, we might find some status property (OK, Failed), any error message either provided directly or as a key to then look-up in a message catalog etc.
This way, we can isolate concerns and only deal with the error messages on the UI layer while being able to use and reuse the validation logic independently.
I was faced with a similar dilemma in the past - I had to write a couple of services that takes data from a 3rd party, manipulating it in various ways, and send that data to other services for further processing.
All of these services might have failed because of wrong or incomplete data, but it was nor unexpected neither exceptional - and I refused to use exceptions for these cases.
I've done an extensive research, reading anything I could get my hands on in this subject in two days, and finally decided the following:
A method might need to return data and might not (sub in Visual Basic, void in Java/C#) - but in both cases, I wanted an indication for success/fail and a potential error message.
If your language of choice supports tuples, you could return a tuple from your methods:
public (bool Success, string ErrorMessage) DoSomething()
{
// implementation here
}
or
public (bool Success, someType Value, string ErrorMessage) DoSomething()
{
// implementation here
}
If not, you can do what I did (That was c#5 - so no value tuples) and create a result class:
public class Result
{
public static Result Success()
{
return new Result(true, null);
}
public static Result Fail(string errorMessage)
{
return new Result(false, errorMessage);
}
protected Result(bool success, string errorMessage)
{
Success = success;
ErrorMessage = errorMessage;
}
public bool Success {get; private set;}
public string ErrorMessage {get; private set;}
}
public class Result<T>
{
public static Result<T> Success(T value)
{
return new Result(true, null, value);
}
public new static Result<T> Fail(string errorMessage)
{
return new Result(false, errorMessage, default(T));
}
private Result<T>(bool success, string errorMessage, T value)
: base(success, errorMessage)
{
Value = value;
}
public T Value {get; private set;}
}
And use it like this:
public Result CouldBeVoid()
{
bool IsOk;
// implementation
return IsOk ?
Result.Success() :
Result.Fail("Something went wrong") ;
}
public Result<int> CouldBeInt()
{
bool IsOk;
// implementation
return IsOk ?
Result.Success(intValue) :
Result.Fail("Something went wrong") ;
}
var result = CouldBeVoid();
if(!result)
// do something with error message
var result = CouldBeInt()
if(result)
// do something with int value
else
// do something with error message
Users often get passwords wrong, it's not an exceptional case.
Yes and no. Whether to throw an exception or not depends on the question you're asking. And in the course of logging a user in, there are typically quite a number of questions being asked before you come to the conclusion whether the user can be logged in or not. The more you break down your code into specialised parts, the more it may make sense to raise exceptions in some of those parts.
Say you specify your login procedure the following way in an HTTP context:
Get the username* and password* from the request.
Fetch the user record* by its username from the database*.
Check whether the record's password* equals* the entered password.
If yes, start a session.
If any of the above steps do not successfully complete, output an appropriate error message.
Any of the items marked with an asterisk above may fail:
The request may not contain a username or password.
There may not be a user record for this username, or the database may be down.
For whatever reason, the record may not have a password and/or be corrupted. The stored password may, for whatever reason, use an unsupported hashing algorithm and hence can't be compared.
It should be rather obvious that in this process there are any number of cases that would be ideal to be implemented as an exception. The actual function which tests the password should probably not throw an exception in case the password is merely false; that should be a boolean return value. But it may still throw an exception for any other number of reasons. If you use exceptions properly, you'll end up with code that looks something like this (pseudo-pseudo code):
try {
username = request.get('username')
password = request.get('password')
user = db.get(username=username)
if (user.password.matches(password)) {
session.start()
} else {
print 'Nope, try again'
}
} catch (RequestDoesNotHaveThisDataException) {
logger.info('Invalid request')
response.status(400)
} catch (UserRecordNotFoundException) {
print 'Nope, try again'
} catch (UnsupportedHashingAlgorithmException, PasswordIsNullException) {
logger.error('Invalid password hash for user ' + user.id)
response.status(500)
print 'Sorry, please contact our support staff'
} catch (DatabaseDownException e) {
// mostly for illustration purposes,
// this exception should probably not even be caught here
logger.exception('SEND HALP!')
throw e
}
So, yes, this is a very simple process, but literally every step along the way has one or more exceptional cases. You ask the question "what is the username the user sent in the request?", and if there's no answer to this question because the user didn't sent any username, you have an exceptional case. Exceptions simplify control flow here a lot as opposed to trying to cover each of these cases with an if..else.
It is NOT an exception if the username is not valid or the password is not correct.
(From the answer you quote from.)
As you can see, we're testing whether the username is "valid" or not by trying to fetch its record from the database. If we have a function whose purpose is to fetch records of users from the database, and there is no such record, then an exception is an entirely valid response. If we defined that function to test whether such a record exists and null or false is a valid return value… fine. But in this case we didn't write it that way, and frankly, that results in simpler control flow I find.
Now, only the password validation itself does not use an exception, since the question asked there is "does this password match that password?", to which the answer can clearly be yes or no. Again, only if something exceptional like an unsupported hashing algorithm turns up can there be no answer to this question and an exception is entirely warranted.
Having said all this, you may notice that most of these cases, except the really fatal one with the database, does not outwardly result in an exception. The component here is expecting and handling certain cases that its sub-components regard as exceptional. This code here is asking the questions, and is prepared to handle Mu as an answer for some of them. Which is to say, a general rule that says "exceptions shouldn't be used in process X, Y or Z because it's not exceptional enough" is too dogmatic. It depends on the purpose of each individual piece of code whether an exception is warranted or not.
Having said all this, what you're asking about is some sort of form validation. The above code shows a case where two pieces of data may each be invalid, and it's using exceptions to in the end still result in a "yes" or "no" response. You can of course encapsulate that in an object like this:
val = new LoginFormValidator()
val.setDataFromRequest(request)
val.validate()
if (val.isValid) {
print 'Hurray'
} else {
print 'You have errors:'
for (error in val.errors) {
print error.fieldName + ': ' + error.reason
}
}
Whether this validator uses exceptions internally for any of this you do not need to care, but in the end it saves all of them as a "yes" or "no" result to its internal properties, from where you can take them either as an aggregate (val.isValid) or individually (for (error in val.errors)).
i am a beginner in grails and i have the following problem. Please help.
package racetrack
class Users {
String userName
String password
static constraints = {
userName(nullable:false, maxSize:20)
password(password:true, minSize: 8,
validator: {
return (it.matches("(.*[\\d])"))?true: ['noNumber']
return (it.matches("(.*[\\W])"))?true: ['noSpecialCh']
return (it.matches("(.*[a-z])"))?true: ['noLower']
return (it.matches("(.*[A-Z])"))?true: ['noUpper']
}
)
}
}
I created the above domain and in message.properties, i added the following:
users.password.validator.noNumber=should contain at least one number
users.password.validator.noLower=should contain at least one lower case letter as well
users.password.validator.noUpper=should contain number as well
users.password.validator.noSpecialCh=should contain number as well
however, i am not given required messages when tried with faulty values. Suppose, if i give no number in the password "should contain at least one number" message was expected but i only get does not match custom validation message.
The core problem is that Groovy, unlike Java, allows multiple return statements. If you converted that to Java it wouldn't compile.
Groovy allows multiple return statements, but obviously only considers the first, so with your code you have one check, not four, essentially
(it.matches("(.*[\\d])")) ? true : ['noNumber']
It should be something like this:
if (!it.matches("(.*[\\d])")) {
return ['noNumber']
}
if (!it.matches("(.*[\\W])")) {
return ['noSpecialCh']
}
if (!it.matches("(.*[a-z])")) {
return ['noLower']
}
if (!it.matches("(.*[A-Z])")) {
return ['noUpper']
}
except that all of the regexes are broken, but that's a separate issue.
Here is my resource:
var app, deps;
deps = ['ngGrid', 'getUsers'];
angular.module('getUsers', ['ngResource'])
.factory('users', function ($resource)
{
return $resource('/Admin/GetUsers', {}, {
query: { method: 'GET', IsArray: true }
});
});
and then I've added code to try to add a step to force parsing:
$scope.myData = users.query(function(response)
{
if (typeof (response) == string)
{
response = JSON.parse(response);
}
});
But it never gets this far, and here's the error in Chrome:
Error: [$resource:badcfg] object
http://errors.angularjs.org/1.2.14/$resource/badcfg?p0=array
at http://localhost:23002/Scripts/angular.js:78:12
at a.module.factory.f.(anonymous function).p.then.m.$resolved (http://localhost:23002/Scripts/angular-resource.min.js:8:517)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at http://localhost:23002/Scripts/angular.js:11132:26
at Scope.$get.Scope.$eval (http://localhost:23002/Scripts/angular.js:12075:28)
at Scope.$get.Scope.$digest (http://localhost:23002/Scripts/angular.js:11903:31)
at Scope.$get.Scope.$apply (http://localhost:23002/Scripts/angular.js:12179:24)
at done (http://localhost:23002/Scripts/angular.js:7939:45)
at completeRequest (http://localhost:23002/Scripts/angular.js:8142:7)
Of course I searched for that error, but I found advice to set IsArray to true or false, this makes no difference. If I set a breakpoint and call JSON.parse on the response string, it gets turned into an array of objects, exactly like what I want. So the string is perfectly valid JSON, but angular appears unwilling to parse it as such, it accepts it as a string and then dies.
My controller is very simple:
public List<ApplicationUser> GetUsers()
{
return AdminUsersViewModel.AllUsers;
}
and then, that method uses a LINQ query to get users from the DB, and then iterates over that collection to create a new one, because before I did that, it just blew up. I've made the call in the browser, and see the same string that is appearing in the angular code.
What I need to know is, why isn't angular spotting that this is a collection of objects, and how can I either force it to parse the string, or change the format so angular can tell what it is ?
Thanks for looking.
OK, I got it. I thought the help I read said to use IsArray ( in hindsight, I think it said DON'T use IsArray ). I knew that was non standard, but that's what I did. I ran the non minified version, and found my error. Change to isArray, and it works.
Thanks for looking :-)
I have to consume a REST webservice which has the following syntax for all requests:
{
message: "OK",
success: true,
results: 1,
data: {
name: "Berlin",
lat: 52.2,
lon: 13.25,
id: 1701
},
(...)
}
When I try to deserialize using:
City source = getRestTemplate().getForObject("http://myws.com/cities/{cityId}", City.class, "1701");
The default HttpMessageConverter tries to look for attributes named message, success, results in the City bean, and since it cannot find them, it's throwing an Exception.
I wonder if there's any way to take advantage of the default HttpMessageConverter but somehow tell it to interpret message, success and results differently, or do I have to create my own HttpMessageConverter altogether?
I had the same issue and the way around it is to create a wrapper object that contains the meta data fields. This method turned out to be quite useful and made it incredibly easy to get at the data.
In your case, the core model is obviously the city but then the wrapper object would be something like this
class CityWrapper{
String message;
String success;
Integer results;
#JsonProperty("data")
City city;
}
When I tackled it I had a list of data coming back and that worked fine with
#JsonProperty("data")
List<City> cities;