Spring-AOP Return value of Aspect #AfterReturn is not working - spring

#AfterReturning(value = "anyPublicMethod() && applyPrivacy()", returning = "result")
public Object afterReturning(JoinPoint joinPoint, Object result) {
return someService.createNewObjectWithHelpOfResult(result);
}
My intention was to fill some null values in result fields. So in method createNewObjectWithHelpOfResult I'm creating a new Object and setting only the required values. But return value is not reflecting after afterReturning method is finished. But if I do mutations on result. They're very well reflected after aspect #AfterReturning method ends, but I want the return value to be used? Is this not possible? I'll have to do mutation only?

What #M.Deinum explained, is documented in the Spring manual, section "After Returning Advice". The end of the section reads:
Please note that it is not possible to return a totally different reference when using after returning advice.
Therefore, you cannot just make your #AfterReturning advice have a return type other than void and hope it will magically return something. As the advice type name implies, all 3 types of #After* advices run after the method has returned already. There is nothing you can do to change the result (except for altering internal state of an object instance). You can merely read (and e.g. log) it.
The solution, like #M.Deinum said, is an #Around advice, see also again the Spring manual.
It is generally a good idea to at least study the manual and learn some basics or take a look at examples before asking questions in public. I am sure you did not find any valid example for an #After* advice with non-void return type.

I am using #AfterReturning on the methods whose return type is String but instead of String I am getting null as result
#AfterReturning(value = "execution(* com.example.demo.aop.business..(..))", returning = "result")
public void afterA(JoinPoint joinPoint, Object result) {
log.info("After method {} returned with value {}", joinPoint, result);
}
O/P - After method execution(void com.example.demo.aop.business.Business2.disp()) returned with value null

Related

Return an item by id

I got this piece of code, I am learning from tutorial. I want to return an element by url which looks like clients/1 instead of clients?id=1. How can I achieve this? Also, can the code below be made easier way?
#GetMapping
public Client getClient(#RequestParam int id) {
Optional<Client> first = clientList.stream().filter(element -> element.getId() == id).findFirst();
return first.get();
}
You may want to use #PathVariable as follows:
#Controller
#RequestMapping("/clients")
public class MyController {
#GetMapping("/{id}")
public Client getClient(#PathVariable int id) {
return clientList.stream().filter(element -> element.getId() == id).findFirst().orElseThrow();
}
Please note, the Optional can be unpacked with orElseThrow method. This will throw a NoSuchElementException in case there is no element found for the id.
Other solution would be to use orElse(new Client(...)) to return a default value if nothing is found.
get() is not really recommended to be used. From the JavaDoc of the get() method:
API Note:
The preferred alternative to this method is orElseThrow().
Even though get() may also throw a NoSuchElementException, similar to orElseThrow, usually the consensus is that get should not be used without isPresent, or should not be used at all. There several other methods to unpack the Optional without forcing you write an if.
The whole idea of the Optional is to overcome this by forcing you to think about the case when there is no value inside.

Pass optional objects as varags in parameter?

I want to pass multiple optional objects in function as varags ?
Optional<ab> ab = Optional.of(ab);
Optional<cd> cd = Optional.of(cd);
Optional<dc> dc = Optional.of(dc);
Optional<ba> ba = Optional.of(ba);
data(ab, cd, dc, ba);
data(Optional<Object>... objects){...}
I am getting error if i don this, any suggestion how can be proceed?
It isn’t related to varargs. You can’t pass an Optional<SomeSpecificType> where an Optional<Object> is expected. They are not compatible.
Assume just (without varargs):
static void data(Optional<Object> object) {
// …
}
Now if we try
Optional<String> ab = Optional.of("");
data(ab);
In my Eclipse I get this error message:
The method data(Optional<Object>) in the type MyClass is not
applicable for the arguments (Optional<String>)
Java generics are defined with this restriction. You also cannot pass, for example a List<String> where a List<Object> is expected.
You can overcome the limitation by declaring the method generic too:
static <T> void data(Optional<T> object) {
// …
}
Or just like this:
static void data(Optional<?> object) {
// …
}
With any of these two declarations the call above is OK.
BTW, #HadiJ is correct in the comment: Optional is meant for return values for from methods that may or may not be there. They have very few other good uses, and as parameters is not one of them. It seems to me that for your use case you should just pass the arguments that are there and leave out those that aren’t. The your data method may receive a longer or shorter argument array, but will just have to handle all elements of the array without caring about Optional. And passing String, Integer, LocalDate, etc, to a method declared void data(Object... objs) is straightforward and poses no problem.

Return method reference

I am playing around in Java 8. How can I return a method reference?
I am able to return a lambda but not the method reference.
My attempts:
public Supplier<?> forEachChild(){
return new ArrayList<?>::forEach;
}
OR
public Function<?> forEachChild(){
return new ArrayList<?>::forEach;
}
You have a small mis-understanding of how method-references work.
First of all, you cannot new a method-reference.
Then, let's reason through what you want to do. You want the method forEachChild to be able to return something that would accept a List and a Consumer. The List would be on which object to invoke forEach on, and the Consumer would be the action to perform on each element of the list. For that, you can use a BiConsumer: this represents an operation taking 2 parameters and returning no results: the first parameter is a list and the second parameter is a consumer.
As such, the following will work:
public <T> BiConsumer<List<T>, Consumer<? super T>> forEachChild() {
return List::forEach;
}
This type of method-reference is called "Reference to an instance method of an arbitrary object of a particular type". What happens is that the first parameter of type List<T> becomes the object on which forEach will be invoked, by giving it as parameter the Consumer.
Then you can use it like:
forEachChild().accept(Arrays.asList("1", "2"), System.out::println);
I would like to add some points.
You can't instantiate unbounded type instance.
List<?> list = new ArrayList<?>();
Second, as Tunaki mentioned, you can't make references to new MyObject::staticMethod when you make method references
The other thing is, forEach(Consumer<T> consumer) (Terminal operation for pipeline streams) doesn't return anything. It only eats whatever we feed it.
-Hope this may help :)

Is it good practice for void methods to return?

The return statement is being used in void methods to break out of the logic here. The problem is the consumers of the method wouldn’t know whether the logic in the method ran completely or not, when we do this. However my architect and teams don't agree with that. The reason is that the current consumer in this case doesn't care about the outcome.
I think this is coding anti-pattern. It is like eating exception with out bubbling it up. What's everyone's opinion on this?
Existing code:
Private void XXX(final String parameter) {
try {
if (parameter==null){
return;
}
....
}
My version
Private boolean XXX(final String parameter) {
try {
if (parameter==null){
return false;
}
....
return true;
}
In general having multiple returns is not necessarily an anti-pattern. At worst there might be many exit points in the method which can be confusing for developers who are reading the code and perhaps make it harder to maintain...maybe but that is not what you seem to be asking.
The code samples you provided appear to me to both be anti-patterns.
The problem is the consumers of the method wouldn’t know whether the logic in the method ran completely or not, when we do this.
First, that is what Exceptions are for. If there is a problem while executing the code in the method, throw an Exception with an intent revealing type and a good message describing the problem.
The first version of your code:
Private void XXX(final String parameter) {
try {
if (parameter==null){
return;
}
....
}
seemed to return instead of throwing an Exception with an invalid argument.
The second version of the code:
Private boolean XXX(final String parameter) {
try {
if (parameter==null){
return false;
}
....
return true;
}
Seems to return a boolean as an exit code of "worked" or "didn't work". This isn't very helpful because if it didn't work, you don't know why. Also it requires the calling code to check the return value which they might forget to do.
There's nothing wrong with having an explicit return for a void method. However, it is good general practice--if possible--to have just one return from a method (although you can have more than one if logic demands it and you write the code as simply as possible--no blocks--so that the overall flow is not obfuscated).
Should you simply return in the case you cite? It all depends on the requirements. Your customers appear to be the programmers who will call this method. Do they consider a null parameter to be a logic error for the method or do they consider it to be valid?
If it's the former then I suggest you use an annotation (#NotNull) to ensure that parameter is not null. Unfortunately, there are several of these to choose from so you will have to figure out which suits your architecture best.
If you really don't want to use an annotation (and null is considered an error) then throw an exception.

Access to pre-interpolated bean validation message template in SpringMVC?

I'm using Spring Validation within a Spring MVC application that delegates validation to Hibernate Validator 5. I'm successfully able to have beans validated and have the messages interpolated by the validator. However, it's important that I also be able to have access to the message template itself, pre-interpolation.
For example, in some bean I have validation #Size(min=5,max=15,message="{my.custom.message}". In a messages.properties file I have entry my.custom.message=test min {min} and max {max}. In my BindingResult, I see the ObjectError with error message "test min 5 and max 15", but I need to look a value up at this point based on the non-interpolated my.custom.message raw value.
Can this be done? If it can't out of the box, can someone point me in the right direction for how I might customize spring's LocalValidatorFactoryBean to preserve this?
Update
I'm looking at extending org.springframework.validation.beanvalidation.SpringValidatorAdapter, and wrapping the getArgumentsForConstraint to automatically append the pre-interpolated message to the returned list of arguments. The notion of exactly what these 'arguments' are and how they're used is unclear to me, but if it's purely used for message interpolation, it seems relatively safe for me to append at the end. Any reason this might not work? Problems it might cause? Better ideas?
Solution
Didn't find any great solutions other than my 'update' above, so I ended up subclassing LocalValidatorFactoryBean with this:
#Override
protected Object[] getArgumentsForConstraint(String objectName, String field, ConstraintDescriptor<?> descriptor) {
if (null == descriptor) return super.getArgumentsForConstraint(objectName, field, descriptor);
Object[] orig = super.getArgumentsForConstraint(objectName, field, descriptor);
if (null == orig || orig.length < 1) return new Object[] { descriptor };
Object[] retval = new Object[orig.length+1];
System.arraycopy(orig, 0, retval, 0, orig.length);
retval[retval.length-1] = descriptor;
return retval;
}
In subsequent code, I look at the last object in this array and test to see if it's an instance of ConstraintDescriptor. Good enough I suppose.
However, it's important that I also be able to have access to the message template itself, pre-interpolation.
In which context do you need to access the template? If it is after validation, then getMessageTemplate() on ConstraintViolation gives you this. If it is within a constraint validator implementation, then you could use getDefaultConstraintMessageTemplate() on ConstraintValidatorContext.

Resources