Calling other request mapping from rest controller - spring

I am trying to call other rest controller from reqest mapping .
#RestController
class MyController{
#Autowired
OtherController other
#RequestMapping(/{token}/add)
public MyDto add(String token){
String[] tokens = token.split("\\.");
I want to call process input from method from Other controller and send token[1] item as path param
}
}
#RestController
public class OtherController{
#RequestMapping(/token/process)
public processInput(#PathVariable token)
{
}
}
How to send spited token to other param as path param. Could you please advice the calling strategy

It is possible to call another controller. You can simply inject your Controller into the class you would like to make that call in. This allows you to use the OtherController controller as if it was a Service component.
#RestController
class MyController {
private final OtherController otherController;
public MyController(#Autowired OtherController otherController) {
this.otherController = otherController;
}
#RequestMapping(/{token}/add)
public MyDto add(String token){
InputDto input=new InputDto();
otherController.processInput(input);
}
}

Related

How to call a service from a controller

I am trying to call the following service from a controller:
#Service
class MyMailService {
private final SendGrid sendGrid;
#Inject
public SendGridMailService(SendGrid sendGrid) {
this.sendGrid = sendGrid;
}
void sendMail() {
Request request = new Request();
Response response = this.sendGrid.api(request);
}
}
And my controller:
# controller
public String index(Model model) {
MyMailService.sendMail() // how to do this properly?
return "register";
}
What would be the correct way to call this from a controller? Basically, I'm trying to "autoconfigure" sendgrid, so I don't have to initialize the SendGrid object with the API key whenever I call the MyMailService class.
As suggested by others, I do think too you need to spend more time learning Java & Spring basics. But to answer your question, you auto-wire/inject your service singleton object in the controller to use it:
#Controller
public class ControllerA
{
.
.
.
#Autowired
private MyMailService mymailService; //singleton object instance injected to be used/shared by all controllers
public String index(Model model) {
mymailService.sendMail()
return "register";
}
.
.
.
}
You can call your service in below ways
1) Simply adding #Autowired to your class type
#Autowired
MyMailService myMailService;
2) Using Constructor Injection as below,
MyMailService myMailService;
#Autowired
public WebController(MyMailService myMailService) {
this.myMailService = myMailService;
}
- here i assumed my Controller name is WebController
3) Using Setter Injection as below,
MyMailService myMailService;
#Autowired
public void setMyMailService(MyMailService myMailService) {
this.myMailService = myMailService;
}
and finally in your controller you can call your service class methods as below,
myMailService.sendMail();
Note:
Follow naming convention.

calling a method by class level annotated with #RequestMapping that includes an autowired class

I am trying to call a method that is annotated with #RequestMapping(signIn) through a class level (from method: authentication) like so:
#RequestMapping(value = /authenticate, method = RequestMethod.POST)
public #ResponseBody Response authentication(HttpServletRequest request)
{
UserController user = new UserController();
return user.signIn(request, null);
}
and my controller looks like:
#Autowired
private UserManager userManager;
#RequestMapping(value = /signin, method = RequestMethod.POST)
public #ResponseBody Response signIn(HttpServletRequest request) {
JsonObject json = Misc.parseJson(request);
String lang = Misc.getLang(request);
user.setEmail(Misc.getEmail(json));
user.setPassword(Misc.getEncryptedPassword(json));
return ResponseUtils.success(userManager.auth(user, lang));
}
user manager is annotated with #component:
#Component
public class UserManager {
public User auth(User user, String lang) {
....
return user;
}
}
Problem is when I call the method "signIn" and just new-up a UserController instance through "/authenticate" mapping, the UserManager becomes NULL. So now I'm assuming that autowiring doesn't work when it's done this way.
Is there any other way to call the signIn method? I would hate to copy paste an already existing code to another class just to get this to work...
Autowiering only works in spring managed bean. If you create a class with new keyword, it is not a spring managed bean and autowiering would not work.
You can try to autowire the class which contains the method which is annotated or better put the code in a service class which can be used by both methods.
It's not problem with #Autowired .There are two type of Annotation
firstly method base annotation and field level annotation. You just used field level annotation.Check your import class with "org.springframework.beans.factory.annotation.Autowired" or it can be problem with initiation of "UserManager"
I don't know why you not moving logic into separate Service classs, but try this:
UserController.java
public UserController(UserManager userManager) {
this.userManager = userManager;
}
and then inside controller where authentication resource method is located:
#Autowired UserManager userManager;
#RequestMapping(value = /authenticate, method = RequestMethod.POST)
public #ResponseBody Response authentication(HttpServletRequest request) {
UserController user = new UserController(userManager);
return user.signIn(request);
}
So in the end I just separated the logic instead. Though one solution that I tried and I could have used was to just add another mapping to the signIn method instead of adding a new method in the other class since the logic was similar. Still I opted for a separate logic instead since there were a lot of unnecessary code in the signIn method for my purpose.

Declaring HttpSession Object in Controller

We have defined a controller and need to declare the HttpSession object. I can autowire it or pass as an object to the method. What is the difference between the two options and which is preferable?
Option 1
#Controller
public class UserController {
#Autowired
HttpSession session;
..
..
}
Option 2
#Controller
public class UserController {
#RequestMapping(value="/user", method=RequestMethod.GET)
public #ResponseBody User getUser(HttpSession session) {
..
..
}
}
In a Controller, you should use Option2.
A session is start from a http request begin, end until the request stop, but the controller is available until the application stoped. So you should not autowired the HttpSession in Controller.
One of the situation you can autowired the http session like that:
#Component
#Scope(value=WebApplicationContext.SCOPE_SESSION)
public class CurrentUserHolder{
#Autowired
private HttpSession session;
public User currentUser() {
return this.get();
}
#Override
public User get() {
return (User)session.getAttribute("currentUser");
}
}
So you can get current user in a service which can not get the session:
#Service
public class UserService{
private #Autowired CurrentUserHolder currentUserHolder;
......
}
If you have more than one methods in your controller which requires HttpSession, the Option 1 is preferrable. Otherwise, you can go with 'Option 2' instead of parameterizing it in every method.

Spring RequestMapping with root path (/{custom})

Let's say my website name is: foo.com
When a user types foo.com, I want to show index.html.
When a user types foo.com/something, I want the server catches the request at the controller.
Here is what I did in the HomeController:
#Controller
public class HomeController {
#RequestMapping(value={"/"}, method=RequestMethod.GET)
public String getHome() {
return "index.html";
}
}
And, the CustomController should catch the request
#Controller
public class CustomController {
#RequestMapping(value={"/{custom}"}, method=RequestMethod.GET)
public String getCustom(#PathVariable String custom) {
// Do something here..
}
}
However, it throws an error: Circular view path [index.html]: would dispatch back to the current handler URL [/index.html] again. It's because the CustomController catches the GET request: foo.com/index.html after the HomeController returns the string: index.html.
I did some research like this:
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets"); // My asset
registry.addResourceHandler("index.html").addResourceLocations("file:/index.html");
} // It's not working
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/" + FileNames.INDEX);
} // This also not working
}
And changing the annotation from #Controller to #RestController in the CustomController is not an option.
Also, I don't have JSP files in the project - they are plain *.html files.
I am using Spring 1.3.3 release, so please help me out.
This solution works with ui-router (AngularJS library). Also, you have to change $resourceProvider setting:
// In your app module config
$resourceProvider.defaults.stripTrailingSlashes = false;
Then, in the Spring server codes, you can do this:
#RequestMapping(value = "/{custom:[^\\.]*}")
public String redirect(#PathVariable String custom) {
// Do something here...
return "forward:/";
}
Found the solution at this link: https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii

Dependency injection in Spring MVC?

I am trying to use dependency injection in my Spring MVC web application. I have a function like this in my controller
#RequestMapping(value = "/stockgoogle/", method = RequestMethod.GET)
public #ResponseBody Stock stockGoogle(Locale locale, Model model) {
StockDaoImpl si = new StockDaoImpl();
//al=s.listCurrent(id);
Stock s=si.listGoogle();
System.out.println("reached here");
model.addAttribute("s", s );
return s;
}
I want to dependency inject StockDaoImpl. Can you please tell me how I can do this. I have been trying to read but most of the explainations are very complex. Should I use #Autowired ? Where should I put it? Can you please help.
You can inject it through the Controller's constructor
class YourController{
private final StockDao dao;
#Autowired
public YourController(StockDao dao){
this.dao = dao;
}
}
And now StockDaoImpl has to be defined as a Bean of course,
#Bean
public StockDao stockDao(){
return new StockDaoImpl();
}
Another way for doing it would be defining StockDaoImpl as a Component
Add below config in Spring config file(for example root-context.xml)
then in your controller, you like below code
class TestController{
#Autowired
private StockDao stockDao;
}
With spring-4 you can directly inject in given way :
#Autowired
private StockDao stockDao;
public #ResponseBody Stock stockGoogle(Locale locale, Model model) {
//al=s.listCurrent(id);
Stock s = stockDao.listGoogle();
System.out.println("reached here");
model.addAttribute("s", s );
return s;
}
Here
StockDao will contain method signature
StockDaoImpl implements StockDao and definition of methods
Autowired will inject that Dao and you can use its method.

Resources