Reputation: 557
I am working with Java Spring framework and JWT - Java Web Tokens. I have below class
import java.util.function.Function;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import app.com.javainuse.config.JwtTokenUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
public class Test {
public static void main(String[] args) {
User u=new User("javainuse", "$2a$10$slYQmyNdGzTn7ZLBXBChFOC9f6kFjAqPhccnP6DxlWXx2lPk1C3G6",new ArrayList<>());
UserDetails ud=u;
JwtTokenUtil jwtTokenUtil=new JwtTokenUtil();
String token = jwtTokenUtil.generateToken(ud);
Test t=new Test();
System.out.println(t.getClaimFromToken(token, Claims::getSubject));
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
System.out.println(claims.toString());
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey("javainuse").parseClaimsJws(token).getBody();
}
}
I am not able to understand statement containing this Claims::getSubject in main method. It gets passed to a functional interface Named Function<Claims,T> claimresolver. How does a method reference getSubject without implementation able to return subject from claims object in getClaimFromToken method ? When we pass method reference to a Functional Interface we the method must have body wight ? but Claims is an interface and getSubject does not have a body then how does "claimsResolver.apply(claims);" is able to get subject value ?
Upvotes: 0
Views: 290
Reputation: 557
I found what it is called in java. It is called unbound non-static method references. Here is a link which explains every type method references and the scenario which I was asking to explain. Unbound Non static method references
Upvotes: 0
Reputation: 103018
someInstance.getSubject()
bakes a cake and returns it to you.
Claims::getSubject
is a recipe for baking cakes.
One does the thing. The other doesn't do anything, it merely is a description of how to do the thing - whatever you hand it to can do the thing, or not, or do it 10 times - or pass the recipe on to somebody else who is then faced with the same choice. They can do whatever they like:
When I write down a recipe for making cake, one of the ingredients I'm going to mention is that you will need fresh water.
That means, to bake a cake, I need fresh water. Or perhaps a tap (something that can make fresh water for me). However, to make a cake recipe I do not need fresh water at all. I just need to tell you (the one who will be following my recipe to bake that cake): "You will need to obtain some fresh water. Not my problem how you do that!".
In other words, a cake recipe is a recipe that turns fresh water (and some other things) into a cake. It does not explain how to obtain fresh water, nor does a recipe for making cake come wrapped around a bottle of fresh water.
In the same vein, Claims::getSubject
is a recipe that explains how to turn any instance of a class that implements Claims
(i.e. a Claims instance) into a String. It does not come with an instance of Claims nor does it explain how to make an instance of Claims. It merely says: IF you have an instance of Claims, this recipe lets you turn that Claims into a String!
Claims::getSubject
specifically says: Take your claims, call it c
. Run c.getSubject()
. Voila, there's your string.
Here, you pass that notion (a recipe for turning claims into strings) to the getClaimFromToken
method, which apparently knows how to produce an instance of Claims.
That's analogous to me handing you a cake recipe today and you showing up with a cake tomorrow. That implies you managed to obtain some fresh water. I do not know how and I don't really need to care - I get to enjoy some cake!
NB: Obviously getClaimsFromToken
knows how to make an instance that implements Claims
from a token, and will then apply your recipe (i.e., call .getSubject()
on it). But that's just 'guessing' - the point of APIs is that they promise they do X. You don't need to bother with knowing how it does it, you just need to bother with knowing what it does, and perhaps ascertaining that the library is fit for purpose and it does what its docs say it does.
Upvotes: 1
Reputation: 93
You're right that the Claims::getSubject
syntax here is passing a method reference to the Function
interface, rather than implementing the full lambda expression.
The key to how this works is that Claims
is an interface that extends the Claims
interface from the io.jsonwebtoken
library.
That io.jsonwebtoken.Claims
interface defines various getter methods like getSubject()
, getIssuer()
etc. without providing implementations.
So when we call:
Claims::getSubject
We are providing a reference to the getSubject()
method on the io.jsonwebtoken.Claims
interface.
Even though the interface doesn't provide an implementation, at runtime the claims
object will actually be an instance of some class that implements the io.jsonwebtoken.Claims
interface and provides a concrete implementation of getSubject()
.
When claimsResolver.apply(claims)
is called, it will invoke that underlying getSubject()
method on the claims
instance, which returns the subject value.
So in summary:
Claims::getSubject
provides a reference to the interface methodclaims
object provides an implementation of that interfaceclaimsResolver.apply(claims)
is able to call the implemented getSubject()
method to return the valueUpvotes: 0