-1

I need to use the value from two variables that are in main/resources/application.properties, both are "custom.data.jwt.secret" and "custom.data.jwt.expiration", the first contains characters and the second numbers.

I attempted all 3 of this answer and did not find other different answers, all return null:

ConfigProperties.java

package com.XX.ZZ.security;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@ConfigurationProperties(prefix = "custom.data.jwt")
@Configuration("JwtData")
public class ConfigProperties {
    private String jwt_secret;
    private long jwt_expiration;

    public String getJwt_secret() {
        return jwt_secret;
    }

    public void setJwt_secret(String jwt_secret) {
        this.jwt_secret = jwt_secret;
    }

    public long getJwt_expiration() {
        return jwt_expiration;
    }

    public void setJwt_expiration(long jwt_expiration) {
        this.jwt_expiration = jwt_expiration;
    }
}

TokenUtils.java

package com.XX.ZZ.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import java.util.*;

public class TokenUtils {

    @Autowired
    private static ConfigProperties configProp;

    private static final String jwt_secret = configProp.getJwt_secret();
    private static final long jwt_expiration = configProp.getJwt_expiration();

    public static String createToken(String name, String email){
        long expirationTime = jwt_expiration * 1000;
        Date expirationDate = new Date(System.currentTimeMillis() + expirationTime);

        Map<String, Object> extra = new HashMap<>();
        extra.put("name", name);

        return Jwts.builder()
                .setSubject(email)
                .setExpiration(expirationDate)
                .addClaims(extra)
                .signWith(Keys.hmacShaKeyFor(jwt_secret.getBytes()))
                .compact();
    }

    public static UsernamePasswordAuthenticationToken getAuthentication(String token){
        try {
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(jwt_secret.getBytes())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

            String email = claims.getSubject();

            return new UsernamePasswordAuthenticationToken(email,null, Collections.emptyList());
        } catch (JwtException e){
            return null;
        }
    }
}

Error: java.lang.NullPointerException: Cannot invoke "com.XX.ZZ.security.ConfigProperties.getJwt_secret()" because "com.XX.ZZ.security.TokenUtils.configProp" is null


ConfigProperties.java

package com.XX.ZZ.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.core.env.Environment;

@Component
@PropertySource("classpath:application.properties")
public class ConfigProperties {

    @Autowired
    private Environment env;

    public String getConfigValue(String configKey){
        return env.getProperty(configKey);
    }
}

TokenUtils.java

package com.XX.ZZ.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import java.util.*;

public class TokenUtils {

    @Autowired
    private static ConfigProperties configProp;

    private static final Long jwt_expiration = Long.valueOf(configProp.getConfigValue("custom.data.jwt.expiration"));
    private static final String jwt_secret = configProp.getConfigValue("custom.data.jwt.secret");

    // same code as the first attempt
}

Error: java.lang.NullPointerException: Cannot invoke "com.XX.ZZ.security.ConfigProperties.getConfigValue(String)" because "com.XX.ZZ.security.TokenUtils.configProp" is null


TokenUtils.java

package com.XX.ZZ.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import java.util.*;

public class TokenUtils {

    @Value("${custom.data.jwt.secret}")
    private static String jwt_secret;
    @Value("${custom.data.jwt.expiration}")
    private static long jwt_expiration;

    // same code as the first attempt
}

Error: java.lang.NullPointerException: Cannot invoke "String.getBytes()" because "com.XX.ZZ.security.TokenUtils.jwt_secret" is null

  • 4
    You can't Autowire fields in classes that are not spring managed. The TokenUtils class isn't spring managed, yet you try to autowire configProp – Stultuske Jan 26 '23 at 13:21
  • no, the moment you instantiate your class as 'myClass = new MyClass();' or similar, you are managing the instantiation. You need to let Spring do all of that. It can be done with a constructor, but not being called like that. annotate it as a Service/Component/... and Autowire it where you want to use it as well – Stultuske Jan 26 '23 at 14:02
  • 1
    First problem: Spring will not inject (autowire) into static fields.; that wouldn't make any sense even if it could. Spring beans are *instances* of classes, but static fields are not associated to any one instance. There are some ugly workarounds but better would be to eliminate the use of static fields. – E-Riz Jan 26 '23 at 14:06
  • @E-Riz if I don't declare these variables as static I get this error: `Non-static field 'jwt_expiration' cannot be referenced from a static context` and if I don't set the function createToken as static I get a related problem from another class "JWTAuthenticationFitler" wich doesn't has anything as static `String token = TokenUtils.createToken(userDetails.getName(), userDetails.getUsername());` and I can't solve that error because the recommendation says that I should make the method createToken static. – LautaroColella Jan 26 '23 at 14:15
  • @Stultuske please read the answer provided by Sivaram, I attempted to use the annotation `@Component`. If what you're saying is to use the `@Component` in TokenUtils and then autowire it where I have to use it I don't see how it would solve the problem, and also my IDE recommends to access it via class reference. – LautaroColella Jan 26 '23 at 14:25
  • 2
    "I don't see how it would solve the problem" you are trying to use Spring dependency injection in a way it can't work. We suggest you use it the way it is supposed to be used, that's the difference. if your entire chain is managed by Spring, Spring can actually autowire your fields. – Stultuske Jan 26 '23 at 14:36

1 Answers1

1

Pass the variables as method params since this class is a static class. I hope you are passing these values from an non-static class. In that class, get the values from application properties as follow.

@Component
public class CallerClass{

    @Value("${custom.data.jwt.secret}")
    private String jwt_secret;
    @Value("${custom.data.jwt.expiration}")
    private long jwt_expiration;

  public void validateToken(){
     TokenUtils.isValid(jwt_secret, jwt_expiration);  
  }

}

public static  class TokenUtils{

   public static boolean isValid(String jwtSecret, long jwtExp){
    //implementation

   }
   
}
Sivaram Rasathurai
  • 5,533
  • 3
  • 22
  • 45