what does javax.validation.valid annotation on return type mean? - rest

recently I came across a method declaration in the following format:
#GET
#Path("/foo")
public #NotNull #Valid String foo()
{
...
}
I have problem understanding what the two annotation #NotNull and #Valid mean. Do they have the same effect if they were declared on top of the method declaration like this?
#GET
#Path("/foo")
#NotNull
#Valid
public String foo()
{
...
}
And it seems that if I have the #Valid annotation on, accessing other endpoints in the same class as foo will also trigger the execution of foo().
Could some one share some opinions?
Thanks in advance.

Do they have the same effect if they were declared on top of the method declaration like this?
YES
Accessing other endpoints should not execute foo() unless foo is called somewhere in your code.
#Valid annotation will execute validation on the return value.

Related

class access control: What if there is readonly access controller?

While I was using class, I found that some attributes, especially the ones which are boolean, are often read by other instances. For example,
class Node{
private:
int item;
bool visited;
public:
bool isVisited(){return visited;}
void bar(){
...
visited=true;
...
}
};
class Graph{
private:
vector<Node> nodes;
public:
void bar(int idx){
if(nodes[idx].isVidited()){
...
nodes[idx].foo();
...
}
}
}
In that case if visited is only changed by the methods of the class Node, then the access controller of the attribute visited shouldn't always be private in perspective of reading. What if there is an access controller 'readonly' that is opened to reading, closed to writing? I think that is useful when defining state attributes. Will there be any side effects?
Have you tried marking the Graph class as friend inside the Node class?
This facilitates accessing the private members of the Node class by the Graph class.
In some languages, there is getter/setter which works as an api of a private value.
It seems like a public value, but internally the methods control the private member variable, not the code with '=' operator itself.
//TYPESCRIPT
class Foo{
private _name:string
constructor(n:string){this._name=n}
get name(){return this._name}
//set name(n:string){this._name=n}
}
const foo=new Foo('Jack jack')
console.log(foo.name) //[LOG]: "Jack jack"
foo.name='hudson' //[ERR]: Cannot set property name of #<Foo> which has only a getter
The code above shows how a readonly property is set. There is only a getter which delivers exactly the same value of the private member variable '_name', but since setter is not defined, only the class itself can change the value and is not able to edit from outside of the class.

#Query in JPA throwing null pointer exception

I am getting nullPointerException from my custom jpa method findShiftNameById() in my shift planner project(github link below). I have used #Query annotation inside ShiftDetailsRepo Interface to implement the method. Please check and let me know what could be causing this. I tried by removing nativeQuery parameter but that gives shift_details not mapped error.I tried by changing datatypes between int and long and also by changing sd.shiftName to sd.shift_name(as per the column name that is available in my actual database) but still same nullPointerException error is coming.
Github link-https://github.com/Anupam5713/shiftPlannerAPI
The method is being called in the ShiftPlanService Class inside the service package
Is there something wrong in my query?
#Query(value = "select sd.shiftName from shift_details sd where sd.shiftId=:shiftId",nativeQuery=true)
public String findShiftNameById(#Param("shiftId") int shiftId);
The following is the cause of NPE. The call to sdr is done before the dependencies are wired.
#Service
public class ShiftPlanService {
#Autowired
ShiftDetailsRepo sdr;
String S1 = sdr.findShiftNameById(1);
String S2 = sdr.findShiftNameById(2);
Move these initializations to a #PostConstruct method.
Example
#PostConstruct
public void initDetails() {
S1 = sdr.findShiftNameById(1);
S2 = sdr.findShiftNameById(2);
}

Spring MVC REST not null constraint does not work on missing request param

Not null validation does not work for a case:
#RestController
public class BookController {
#GetMapping("/api/books/search")
public Page<Book> get(#RequestParam(name = "bookId") #Valid #NotNull Long bookId, Pageable pageable) {
.... // #1
}
}
If I call GET http://localhost:8080/api/books/search?bookId=
bookId is null on row #1. It's strange behaviour, cause if I do not provide bookId it fails.
#NotNull validation is not triggered.
#NotNull validation is not triggered.
When you want the validation to be triggered, the controller class must be annotated with #Validated:
#Validated
#RestController
public class BookController {
...
}
Quoting the documentation:
To be eligible for Spring-driven method validation, all target classes need to be annotated with Spring’s #Validated annotation.
The #RequestParam annotation has a required element where the default value is true. It simply indicates that the parameter itself must be present in the URL (either ?id or ?id=), but it doesn't require a non-null value for that parameter. If you need to validate the value of such parameter, then you should use Bean Validation annotations.
Consider, for instance, the following controller method:
#GetMapping("/foo")
public ResponseEntity<Foo> get(#RequestParam("id") Long id) {
...
}
The following request will result in a response with the 400 status code because the id parameter is not present:
GET /foo HTTP/1.1
Host: example.org
On the other hand, the following request is considered to be valid because the id parameter is present (even though there's no value associated with it):
GET /foo?id HTTP/1.1
Host: example.org
To refuse null values, use the #NotNull annotation (and ensure that controller class is annotated with #Validated):
#GetMapping("/foo")
public ResponseEntity<Foo> get(#RequestParam("id") #NotNull Long id) {
...
}
There are different concepts. Method parameters annotated with #RequestParam are by default required. You can set #RequestParam(required = false) to disable this.
Your parameter however is of type Long (object). You can not give it and then by default it will be null (since you did not set a default - like #RequestParam(defaultValue = )).
Best way is to either set a default value or to check for null in your method.

mapStruct: map list to other list?

I have a list List<Payment> which I'd like to map to another list List<PaymentPlan>. These types look like this:
public class Payment {
#XmlElement(name = "Installment")
#JsonProperty("Installment")
private List<Installment> installments = new ArrayList<>();
#XmlElement(name = "OriginalAmount")
#JsonProperty("OriginalAmount")
private BigDecimal originalAmount;
//getters setters, more attributes
}
and....
public class PaymentPlan {
//(Installment in different package)
private List<Installment> installments;
#XmlElement(name = "OriginalAmount")
#JsonProperty("OriginalAmount")
private BigDecimal originalAmount;
//getters setters, more attributes
}
I expect that something like this is working...
#Mappings({
#Mapping(//other mappings...),
#Mapping(source = "payments", target = "paymentInformation.paymentPlans")
})
ResultResponse originalResponseToResultResponse(OrigResponse originalResponse);
...but I get:
Can't map property java.util.List<Payment> to java.util.List<PaymentPlan>.
Consider to declare/implement a mapping method java.util.List<PaymentPlan> map(java.util.List<Payment> value);
I don't know how to apply this information. First I though I need to declare some extra mapping (in the same mapper class) for the lists, so MapStruct knows how to map each field of the List types like this:
#Mappings({
#Mapping(source = "payment.originalAmount", target = "paymentInformation.paymentPlan.originalAmount")
})
List<PaymentPlan> paymentToPaymentPlan(List<Payment> payment);
...but I get error messages like
The type of parameter "payment" has no property named "originalAmount".
Obviously I do something completely wrong, since it sound like it does not even recognize the types of the List.
How can I basically map from one List to another similar List? Obviously I somehow need to combine different mapping strategies.
btw: I know how to do it with expression mapping, like...
#Mapping(target = "paymentPlans",expression="java(Helper.mapManually(payments))")
but I guess MapStruct can handle this by iself.
I presume you are using version 1.1.0.Final. Your extra mapping is correct, the only difference is that you need to define a mapping without the lists MapStruct will then use that to do the mapping (the example message is a bit misleading for collections).
PaymentPlan paymentToPaymentPlan(Payment payment);
You don't even need the #Mappings as they would be automatically mapped. You might also need to define methods for the Instalment (as they are in different packages).
If you switch to 1.2.0.CR2 then MapStruct can automatically generate the methods for you.

Interface query parameter parsing?

I believe this is not possible, but I just wanted to verify.
I would like to do something like...
#Path("/awesome")
public class MyRestResource {
#GET
public void coolQuery(#QueryParam("user") User) {
// ...
}
}
public interface User {
String name();
Address address();
}
(Please don't comment on the example... it's completely made-up and not my use case.)
I imagine this is not possible because Jersey/JAX-RS generally requires a static method public static T valueOf(String input) which obviously is not possible with interfaces.
That said, is there any work-around for this to have a query parameter be an interface? And if so, how do you specify the parser / parsing logic?
Thanks
According to the documentation there are more ways than just the static valueOf method:
Be a primitive type;
Have a constructor that accepts a single String argument;
Have a static method named valueOf or fromString that accepts a single String argument (see, for example, Integer.valueOf(String) and java.util.UUID.fromString(String));
Have a registered implementation of javax.ws.rs.ext.ParamConverterProvider JAX-RS extension SPI that returns a javax.ws.rs.ext.ParamConverter instance capable of a "from string" conversion for the type. or
Be List<T>, Set<T> or SortedSet<T>, where T satisfies 2 or 3 above. The resulting collection is read-only.
The solution using a ParamConverterProvider should work in this case.