2

I would like to invoke a Controller's method via a Java class, so I can return a specific view. In this case I have a short list of IDs; if the current user's ID is not in that list, redirect to a view invalidUser.

I can do it on the client-side with either Ajax or a button: onclick="location.href='/invalidUser'

But I am not clear on how I can call the ViewsController's invalidUser() method from a Java class.

How can I do that with Java in the invalidUserRedirect() method? I was thinking to get the base URL from the HttpServletRequest as shown here: Get Root/Base Url In Spring MVC and then make an http call to baseUrl + "/invalidUser" but that does not seem like the right approach.

AuthService:

@Service
public class AuthService {

  public void invalidUserRedirect(HttpServletRequest request) {
    // Make call to invalidUser() in ViewsController
  }
}

Views Controller:

@Controller
public class ViewsController {
  @RequestMapping(value = "/invalidUser", method = {RequestMethod.GET})
  public String invalidUser() {
    return "invalid";
  }

}

Boris
  • 566
  • 5
  • 18
  • what is the requirement here? why do you wish to call a controller from within a service? – Lalit Mehra May 21 '19 at 18:03
  • Simply put, even if you manage to call the controller method from the service, the result would not be `a specific view`, it would be the string `invalid`. – The Head Rush May 21 '19 at 18:06
  • @Boris Try to rethink what is your goal. Is it calling a method in the controller, or rather returning a specific, rendered view? – Lesiak May 21 '19 at 18:49
  • What you could do is throw a custom made Exception from your service and catch it in an `@ExceptionHandler`. Then you return a response with a redirect. – GabLeg May 21 '19 at 19:23

3 Answers3

3

Controller classes are called from your browser. You shouldn't call a Controller method from your service class. Your controller method should call invoke your service class

nLee
  • 1,230
  • 2
  • 10
  • 20
1

Controller class generally used for redirecting flow of application based on your business logic. Most of all the method in controller are marked with @RequestMapping annotation, even though you are able to call the controller method from the service, it will not able to fulfill the purpose as the return type of Controller is resulting specific view. You have to write implementation of AuthenticationFailureHandler to achieve the functionality. This is easily achievable by spring security

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

@Component
public class MyAuthenticationFailureHandler  implements AuthenticationFailureHandler{

@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
    AuthenticationException exception) throws IOException, ServletException {
    request.setAttribute("param", "invaliduser");
    response.sendRedirect("/domain/?error");
} }

Call this class in the Security class

@Autowired
 MyAuthenticationFailureHandler failureHandler;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
  http.formLogin()
                .loginPage(LOGIN_URL)
                .failureUrl(LOGIN_URL + "?error").permitAll()
                .authenticationDetailsSource(authDetailsSource)
                .successHandler(successHandler)
                .failureHandler(failureHandler);
      }
0

The controller must determine which services to invoke based on user requests.
The service does not determine the controller.
I think it is not good practice.
Your Controller should be like this:

@Controller
public class ViewsController {

    @Autowired
    private UserValidator userValidator;

    @RequestMapping(value = "/testUser", method = { RequestMethod.GET })
    public String testUser(UserInfo userInfo) {
        //call service
        boolean isValidUser = userValidator.test(userInfo);
        if(isValidUser)
            return "validUserPage";
        else
            return "invalid";
    }
}
HolyMoly
  • 36
  • 3