I run into a problem with JSR-303 bean validation with a Groovy class that implements Traits with additional fields (plus their constraints). Let me show you a simple example. I have a class called ClientInfo which looks like this:
class ClientInfo implements AddressInfo, ContactInfo, BusinessEntity { }
It implements 3 traits that provides additional information. AddressInfo may look like this:
trait AddressInfo {
#Size(max = 128)
#SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE)
String contactName
#Size(max = 255)
#SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE)
String addressLine1
#Size(max = 255)
#SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE)
String addressLine2
#Size(max = 32)
#SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE)
String postalCode
#Size(max = 64)
#SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE)
String city
#Size(max = 3)
#SafeHtml(whitelistType = SafeHtml.WhiteListType.NONE)
String countryCode
}
So far everything looks good. The problem shows up when the constraint validation fails. For example, if countryCode field fails during ClientInfo instance validation, it holds error message under the AddressInfo__countryCode field name:
{"AddressInfo__countryCode":"size must be between 0 and 3"}
It is caused by the fact that the fields that come from the trait are compiled into e.g. AddressInfo__countryCode, AddressInfo__addressLine1 and so one, providing getters and setters for those fields.
I tried to use Jackson annotations like #JsonProperty('countryCode') over the countryCode field in the AddressInfo trait, but it didn't help (the annotation was added to compiled class).
My question is: is it possible to use e.g. Jackson property mappers to render field names provided in #JsonProperty('...') annotation for the fields provided by implemented trait? I will really appreciate your help.
PS: I'm using 'org.hibernate:hibernate-validator:5.1.3.Final' bean validation implementation (maybe this one should be change).
Related
I am trying to retrieve the common items across two lists using Groovy. The following code works just fine, i.e the output from running this code is "DEBUG found in common Items : same". So far so good!
def list1 = ["same", "different"]
def list2 = ["same", "not the same"]
def commonItems = list1.intersect(list2)
for(int i=0; i < commonItems.size(); i++)
{
log.info("DEBUG found in common Items : " + commonItems[i])
}
I hit an issue when I try to apply the above principle to a list of objects - my issue is that the 'commonItems' list does NOT contain the single object I would expect, but is empty. Please note, my custom object 'ErrorWarningDetail' does override compareTo. Can someone see what I am doing wrong / make any suggestions? Thanks in advance!
First of all here is my custom class - note 'CompateTo' just checks the 'Code' field for now.
class ErrorWarningDetail implements Comparable
{
public String Code
public String Description
public String ErrorType
public String State
#Override
int compareTo(Object o) {
int result = Code <=> o.Code
result
}
}
Now here is the code that does the business. I would expect one object to be in 'commonItems' but it is infact empty - what am i doing wrong here? The output of running this is "DEBUG no common items"
def similarONE = new ErrorWarningDetail()
similarONE.Code = "100-1"
def similarTWO =new ErrorWarningDetail()
similarTWO.Code = "100-1"
def completelyDifferent = new ErrorWarningDetail()
completelyDifferent.Code = "697-2"
def List1 = []
def List2 = []
List1.add(similarONE)
List1.add(completelyDifferent)
List2.add(similarTwo)
def commonItems = list1.intersect(list2)
if (commonItems.size() == 0)
{
log.info("DEBUG no common items")
}
Implementing compareTo() is not enough in Java, you should be implementing equals/hashCode instead.
In Groovy there's a handy annotation for that. So, the script down below executes successfully:
import groovy.transform.EqualsAndHashCode
#EqualsAndHashCode( includes = [ 'code' ] )
class ErrorWarningDetail implements Comparable {
String code
String description
String errorType
String state
#Override
int compareTo(Object o) {
code <=> ( o?.code ?: '' )
}
}
def similarONE = new ErrorWarningDetail( code:"100-1" )
def similarTWO = new ErrorWarningDetail( code:"100-1" )
def completelyDifferent = new ErrorWarningDetail( code:"697-2" )
def list1 = [similarONE, completelyDifferent]
def list2 = [similarTWO]
def commonItems = list1.intersect list2
assert 1 == commonItems.size()
P.S. Please, DO NOT name fields starting with Capital letters!
The equals and hashCode are the methods utilized to determine object equality, so the intersect method would rely on those.
The compareTo method is utilized for sorting purposes.
Groovy has some convenient utilities for common tasks in the package groovy.transform
Below is the modified class with the annotations that makes it work as intended.
#EqualsAndHashCode(includes=["Code"])
#ToString(includeFields=true)
class ErrorWarningDetail implements Comparable
{
String Code
String Description
String ErrorType
String State
#Override
int compareTo(Object o) {
Code <=> o?.Code
}
}
I am getting this error when unmarshalling an xml
java.lang.NumberFormatException:
at com.sun.xml.bind.DatatypeConverterImpl._parseDouble(DatatypeConverterImpl.java:232)
while checking on the xml and my classes for double values, I've found one of the elements of the xml that has a null value for its double attribute (I know it is double because the others of the same element have a double attribute)
<data num = "">...</data>
data class
public class Data implements Serializable {
...
#XmlAttribute(name = "num")
private double num;
//private Double num; //same problem as above
...}
can the num attribute be parsed to double if it was null? or is it fine?
Boxing Conversion can be acheived by using as keyword
So I tried to perform boxing using as keyword.
So I tried the below example
Eg 1:-
int i = 12;
string a = i.ToString(); // Boxing Conversion
Console.WriteLine(a); //This works
Console.ReadKey();
Eg 2:-
var aa = i as object; // This works
var a = (i as string) // Compile time error
var a = (i as string).ToString(); // Compile time error
Can anyone explain why boxing can't be performed using as keyword for a string reference type?
1)
int i = 12;
string a = i.ToString();
ToString() is not a boxing conversion at all (and I'm not sure the term is quite right - boxing is just boxing). It is conversion to string. "a" is totally different object, not related to i anymore. It's type is string and value is "12", not 12.
2)
int i = 12;
var aa = i as object;
It is boxing, but aa still keeps object of int type.
var a = (i as string)
Here you are trying to convert int to string, which is impossible to do what way.
What you are trying to do here is usual in many languages, like JavaScript. But C# has very strong rules about type conversions. And most of the time, you cannot just cast type to string and back.
I would like to store a string as a constant in Swift so I can reuse it and inject variables into it. For example, I can do this in C#:
var template = "Your name is {0} and your age is {1}."
someLabel.text = string.Format(template, "John", 35)
some2Label.text = string.Format(template, "Jane", 33)
How can I accomplish this in Swift so I can reuse the string template?
Use swift's printf-style syntax to save the template and then use it like this:
var template = "Your name is %# and your age is %d."
someLabel.text = String(format: template, "John", 35)
some2Label.text = String(format: template, "Jane", 33)
If you haven't used this style of syntax before here is a rough guide:
%# : String (or, as nhgrif pointed out, the description / descriptionWithLocale property of an NSObject)
%d : Int
%f : Double
%.2f : Double with precision of 2, e.g. 2.2342 -> 2.23
Here's the documentation if you require more precision.
You already have an answer, but if you want type safety and to localize your code, you can use enums like this:
enum Greeting: CustomStringConvertible {
case SayHello(String)
var description:String {
switch (self) {
case .SayHello(let name):
return "Say hello to \(name)?"
}
}
}
let a = Greeting.SayHello("my little friend")
Note that doesn't preclude you from taking a hybrid approach of putting all your string templates in one location and building them in a type safe enum via the String(format:...) approach. You would just need to implement it carefully (but only once).
You can use a template engine such as https://github.com/groue/GRMustache.swift.
In the documentation/section 14.4 I came accross with the following example of code:
task configure << {
def pos = configure(new java.text.FieldPosition(10)) {
beginIndex = 1
endIndex = 5
}
println pos.beginIndex
println pos.endIndex
}
It's not quite clear what the pos and the configure means. I thought configure is just a property, so we can write something like
println configure.beginIndex
but the line causes compile-time error. And
{
beginIndex = 1
endIndex = 5
}
is just a closure, is it?
configure() is a method of the gradle Project object. The documentation of this method explains what it does:
Object configure(Object object, Closure configureClosure)
Configures an object via a closure, with the closure's delegate set to the supplied object. This way you don't have to specify the context of a configuration statement multiple times.
Instead of:
MyType myType = new MyType()
myType.doThis()
myType.doThat()
you can do:
MyType myType = configure(new MyType()) {
doThis()
doThat()
}
So the manual snippet defines an object of type FieldPosition, assigns it to the variable pos, sets its beginIndex and endIndex properties using a closure, thanks to the configure() method of Project, and then prints these properties.
It's a pointless example showing how to use the gradle DSL to configure several properties of an object.