How to call Spring Boot RESt api using Spring MVC? - spring-boot

I have created REST api using Spring Boot.
So, that is the fragment of it:
#RestController
#RequestMapping("/api/employee")
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#GetMapping(value = "/all", produces = "application/json")
public ResponseEntity<List<Employee>> getAllEmployees() {
return ResponseEntity.ok(employeeService.findall());
}
Now, I would like to create more like MVC application part - simple view that shows all Employees using thymeleaf. (Just simple UI to use this app more convinient than sending curl requests)
#Controller
public class MainPageController {
#GetMapping("/employees")
public String showEmployees() {
// i don't know what to do here
return "employeesPage";
}
What is the appropriate way to do so? Is there a more simple way to do it?
Looking forward for your answers!

So you do exactly the same you did on your EmployeeController but instead of a JSON, you return a view.
Get your employes through EmployeeService and put them on a collection
Create your employee view under /templates folder (many tutorials of how to do it)
return this view with your collection of employees
Example:
#GetMapping(value = "employees")
public ModelAndView showEmployees() {
ModelAndView mav = new ModelAndView("employeesPage");
mav.addObject("employees", employeeService.findall());
return mav;
}
Check here for more detailed info:
https://www.thymeleaf.org/doc/articles/springmvcaccessdata.html

Related

Thymleaf not returning templates but strings

I'm building an application with thymeleaf, and i've encountered this problem where when returning a template as for example ...return "products";... and when I visit the url i addressed in #GetMapping() i get the string "products" instead of rendered template
.
#Service
public class HomeService {
#Autowired
ProductRepository productRepository;
public String getProducts(Model model) {
List<Product> products= productRepository.findAll();
if (!products.isEmpty()){
model.addAttribute("product", products);
return "products";
}else{
return "404";
}
}
}
#RestController
public class HomeController {
#Autowired
HomeService homeService;
#GetMapping("/home")
public String home(Model model){
return homeService.getProducts(model);
}
}
As stated above, the #RestController annotation should be replaced with the #Controller annotation.
The #RestController annotation in Spring is designed for building REST web services that return data in JSON or XML format, and it does not support the use of view templating engines like Thymeleaf. If you want to render HTML views, you should use the #Controller. In #Controller, we can return a view in Spring Web MVC.
Use #Controller, #RestController is for RestAPI only, and not MVC ;)

Controller or RestController

i'm new to jEE, and this is my first jEE code using spring. The code bellow is working fine. He just print the string index when i go to my localhost; and otherwise he print handling error.
My question is: Why this code isn't working anymore if I use #Controller instead of #RestController
I can't find any simple explanation in the docs from spring and I was hoping someone could explain this.
I have the feelings that a controller alone can't work without something like thymeleaf (I know if I were using thymeleaf the string index would be replaced by the index page from the ressources folder) where a RestController might be returning data as xml or json or something else.
Thanks
#RestController
public class HelloController implements ErrorController {
#RequestMapping("/")
public String index() {
return "index";
}
#RequestMapping("/error")
public String error() {
return "gestion erreur";
}
#Override
public String getErrorPath() {
return "/error";
}
}
The job of #Controller is to create a Map of model object and find a view but #RestController simply return the object and object data is directly written into HTTP response as JSON or XML.
The #Controller is a common annotation which is used to mark a class as Spring MVC Controller while #RestController is a special controller used in RESTFul web services and the equivalent of #Controller + #ResponseBody.
If you want the same functionality of #RestController without using it you can use #Controller and #ResponseBody.
#Controller
public class HelloController{
#RequestMapping("/")
#ResponseBody
public String index() {
return "index";
}
}

How can I add textbox/textfield in my swagger page built in Spring boot?

I am trying to auto-generate the swagger page for a RestAPI in Spring Boot using annotations.
Code of Controller:
#RestController
#Api(value="UserManagementAPI", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserManagementController {
#RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}
#ApiOperation(value="add a pro",consumes="application/json")
#RequestMapping(value = "/getUser", method = RequestMethod.GET, produces="application/json")
public static List<UserDetails> getUser(#PathVariable(name="id") String id) throws UserException
{
return UserHelper.getUserByEmail(id);
}
Application.java
#SpringBootApplication
#EnableSwagger2
#Configuration
#ComponentScan({ "userManagement"})
#EnableAutoConfiguration
public class Application {
#Bean
public Docket simpleDiffServiceApi() {
return new Docket(DocumentationType.SWAGGER_2).groupName("userManagement").apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.any())
// .paths(PathSelectors.any())
// Will also include the basic error controllers by default
.paths(Predicates.not(PathSelectors.regex("/error")))
// Exclude basic error controllers
.build().pathMapping("/");
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Business Location Service")
.description("Spring Boot REST APIs for Business Location Service")
.contact(new Contact("EntSol-IoT (Niche Technology Delivery Group)", "http://somewebsite.com",
"some#mail.com"))
.version("1.0").build();
}
In the swagger page, I can see all my APIs. But there are more. It is showing all possible method type (e.g POST, GET, PUT etc.) though in Controller I only wrote GET method.
Another issue is that there is no Textbox in the swagger page under the API where I can search for the id. May be I am missing something. I have been trying to resolve it for past two days. But couldn't help myself. Thanks in advance.
I got the problem. Your getUser method is declared as static. Please remove static, for it to work.
public List<UserDetails> getUser(#PathVariable(name="id") String id) throws UserException { }

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.

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