Search code examples
javaspringraygun

Get parameter value from method in another class


What I'm trying to achieve is, using Raygun (a crash reporting service), send the user details of the user who experienced the issue.

I originally tried using a method similar to this to get the username:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
username = authentication.getName();

But for some reason this returned the value, ipaduser. I'm not sure where that value comes from but this obviously isn't the answer.

I then tried:

System.getProperty("user.name");

But this just gets the name of the logged in user for our API server, not the username of the user using the application.

After some digging around, I discovered that the username and name of the database for a user is being stored in a custom object called ApiAccessToken. The problem is, that this ApiAccessToken object is only being set in methods in our Controller classes.

For instance:

@RequestMapping(path = "/api/foo", method = RequestMethod.GET)
public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey{
    ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
    // Etc
}

The code for ApiAccessToken and validateApiKey() are as follows:

public final class ApiAccessToken {

    private String databaseName;
    private String username;

    public String getDatabaseName() { return databaseName; }

    public void setDatabaseName(String databaseName) { this.databaseName = databaseName; }

    public String getUsername() { return username; }

    public void setUsername(String username) { this.username = username; }
}

And

protected ApiAccessToken validateApiKey(ApiKeyService apiKeyService, String apiKey){
    UserAccountJdbcRepository userAccountJdbcRepository = new UserAccountJdbcRepository(createDataSourceForDatabase(USERS_DATABASE_NAME));
    ApiAccessToken accessToken = apiKeyService.validateApiKey(userAccountJdbcRepository, apiKey);
    if (accessToken == null) {
        throw new InvalidApiKeyException();
    }
    return  accessToken;
}

My other idea was having a local variable in the Controller class that would store the value of apiKey and then I would pass that value to the other method using a getter. For example, in the Controller class:

private static String apiKey;

public static String getApiKey() { return apiKey; }

@RequestMapping(path = "/api/foo", method = RequestMethod.GET)
public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey{
    ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
    apiKey = this.apiKey; 
    //Etc
}

And then in the class where I'm sending exception details to Raygun:

 String apiKey = Controller.getApiKey();
 ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
 username = accessToken.getUsername();
 database = accessToken.getDatabaseName();

But that just returns a NullPointerException and doesn't send anything to Raygun.

Any help would be greatly appreciated as I'm not entirely sure what else to try. Let me know if there's anything I've left out that you think I should include. Once again, I'm still pretty new to Spring MVC and the developer who wrote most of this is no longer employed with us.


Solution

  • With the suggestion from Minh Hoang, I was able to solve this issue.

    I added a global variable to the class RaygunUnhandledExceptionHandler:

    private static ApiAccessToken accessToken = new ApiAccessToken();
    

    I then wrote this method in RaygunUnhandledExceptionHandler to get the accessToken and set it to the variable I declared above:

    public static void getAccessTokenFromController(ApiAccessToken accessTokenFromController) { accessToken = accessTokenFromController; }
    

    I then added this line to /api/foo in the Controller so that it would send the accesstoken to RaygunUnhandledExceptionHandler:

    // Sends the API Key to RaygunUnhandledExceptionHandler
    RaygunUnhandledExceptionHandler.getAccessTokenFromController(accessToken);
    

    And then in defaultErrorHandler() in RaygunUnhandledExceptionHandler:

    ArrayList tags = new ArrayList<String>();
    tags.add("username: " + accessToken.getUsername());
    tags.add("database: " + accessToken.getDatabaseName());
    


    Thanks again to Minh Hoang and fantaghirocco for your assistance in helping me sort this out.

    Please let me know if you see any issues with this implementation.