Tomcat: The requested resource [/] is not available: without web.xml - spring

I'm doing spring, web-mvc app.
In controller UserController I have
#RequestMapping("/"), #GetMapping empty.
Prefix: setPrefix("/WEB-INF/pages/")
Suffix: setSuffix(".html")
Therefore the file all_users.html should be found?
#GetMapping
public String getAllUsers(Model model) {
model.addAttribute("users", userService.getAllUsers());
return "all_users";
}
https://github.com/anatoliy19/testCRUD.git

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 ;)

I get 404 error when I try endpoint on localhost

When I try GET on localhost:8080/path I get 404 error.
endpoint:
#Path("path")
#Produces(MediaType.TEXT_PLAIN)
public Controller {
#GET
public String getString() {
return "hello";
}
}
project structure looks like this:
com.example.demo.controller.Controller.java
com.example.demo.DemoApplication.java
Project is generated with Spring Initializr with spring web and lombok and nothing else.
You are using JAX-RS with Spring Boot. You must use Spring MVC
#RestController
#RequestMapping("/path")
public Controller {
#GetMapping
public String getString() {
return "hello";
}
}
You should start with reading the documentation:
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-developing-web-applications
https://spring.io/guides/gs/rest-service/

Springboot #Controller cannot be invoked, but #RestController works

My controller has been annotated with #Controller and it cannot be invoked
- The browser shows
There was an unexpected error (type=Not Found, status=404).
But, if it is annotated with #RestController, then it works. My SpringBoot version:1.5.3.RELEASE
My Controller : (in com.sbootsecurityjsp.controller)
#Controller
public class LoginController {
#RequestMapping(value = "/login", method= RequestMethod.GET )
public String login() {
return "Login Controller";
}
}
Main Class: (in com.sbootsecurityjsp)
#SpringBootApplication(scanBasePackages = {"com.sbootsecurityjsp"})
public class SbootSecurityJspApplication {
public static void main(String[] args) {
SpringApplication.run(SbootSecurityJspApplication.class, args);
}
}
I am curious why the #Controller cannot work if the #RestController annotation works. If component scan is not working, #RestController also should not work. I have added scanbasePackages too. Even without scanbasePackages, it does not work.
By the way, when the app starts, the logs also show a line as following:
INFO 532 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/login],methods=[GET]}" onto public java.lang.String com.sbootsecurityjsp.controller.LoginController.login()
Why #Controller is used is to differentiate requests to pages and rest calls. Please correct me if I am wrong. My idea is to use #RestController s for REST requests, on the other hand #Controller for pages related requests- redirecting to JSP or any logics related to views. Is it a bad practice ?
Why does it return a 404 when I use #Controller annotation?
When using #Controller, Spring expects the String you return in #RequestMapping methods to correspond to the page you want to redirect the user to.
#RequestMapping(value = "/login", method= RequestMethod.GET )
public String login() {
return "Login Controller";
}
Here, Spring will try to redirect the user to Login Controller.jsp, which cannot be found and thus returns a 404.
Why does it not return 404 when I use #RestController
When using #RestController, the String you return is not mapped to any page. Instead, Spring just transforms it to e.g. a JSON response. This is why this doesn't give you a 404.
Proposed solution
If you have a jsp page called login.jsp, simply return "login":
#RequestMapping(value = "/login", method= RequestMethod.GET )
public String login() {
return "login";
}

Spring boot #GetMapping for root not working

My Spring Boot controller is working just fine, except that I cannot create a mapping for the home directory. I have tried:
#Controller
public class MyController {
#GetMapping(value = {"/"})
public ModelAndView searchPage(Locale locale) {
ModelAndView model = new ModelAndView();
model.setViewName("pageTemplate");
return model;
}
}
#GetMapping(value = "/")
#GetMapping(value = "")
#GetMapping
#RequestMapping with all values above
I always get my 404 error page. If this is supposed to work, how can I debug why it is not?
Found it. I set in application.properties:
logging.level.org.springframework.web: DEBUG
which then displayed
o.s.w.s.mvc.ServletForwardingController : Forwarded to servlet [springVaadinServlet] in ServletForwardingController 'vaadinUiForwardingController'
It turns out that I have used #SpringUI without specifying a path

404 while using Spring cloud FeignClients

This is my setup:
First service(FlightIntegrationApplication) which invoke second service(BaggageServiceApplication) using FeignClients API and Eureka.
Project on github: https://github.com/IdanFridman/BootNetflixExample
First service:
#SpringBootApplication
#EnableCircuitBreaker
#EnableDiscoveryClient
#ComponentScan("com.bootnetflix")
public class FlightIntegrationApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FlightIntegrationApplication.class).run(args);
}
}
in one of the controllers:
#RequestMapping("/flights/baggage/list/{id}")
public String getBaggageListByFlightId(#PathVariable("id") String id) {
return flightIntegrationService.getBaggageListById(id);
}
FlightIntegrationService:
public String getBaggageListById(String id) {
URI uri = registryService.getServiceUrl("baggage-service", "http://localhost:8081/baggage-service");
String url = uri.toString() + "/baggage/list/" + id;
LOG.info("GetBaggageList from URL: {}", url);
ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
LOG.info("GetProduct http-status: {}", resultStr.getStatusCode());
LOG.info("GetProduct body: {}", resultStr.getBody());
return resultStr.getBody();
}
RegistryService:
#Named
public class RegistryService {
private static final Logger LOG = LoggerFactory.getLogger(RegistryService.class);
#Autowired
LoadBalancerClient loadBalancer;
public URI getServiceUrl(String serviceId, String fallbackUri) {
URI uri;
try {
ServiceInstance instance = loadBalancer.choose(serviceId);
uri = instance.getUri();
LOG.debug("Resolved serviceId '{}' to URL '{}'.", serviceId, uri);
} catch (RuntimeException e) {
// Eureka not available, use fallback
uri = URI.create(fallbackUri);
LOG.error("Failed to resolve serviceId '{}'. Fallback to URL '{}'.", serviceId, uri);
}
return uri;
}
}
And this is the second service (baggage-service):
BaggageServiceApplication:
#Configuration
#ComponentScan("com.bootnetflix")
#EnableAutoConfiguration
#EnableEurekaClient
#EnableFeignClients
public class BaggageServiceApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(BaggageServiceApplication.class).run(args);
}
}
BaggageService:
#FeignClient("baggage-service")
public interface BaggageService {
#RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
List<String> getBaggageListByFlightId(#PathVariable("flight_id") String flightId);
}
BaggageServiceImpl:
#Named
public class BaggageServiceImpl implements BaggageService{
....
#Override
public List<String> getBaggageListByFlightId(String flightId) {
return Arrays.asList("2,3,4");
}
}
When invoking the rest controller of flight integration service I get:
2015-07-22 17:25:40.682 INFO 11308 --- [ XNIO-2 task-3] c.b.f.service.FlightIntegrationService : GetBaggageList from URL: http://X230-Ext_IdanF:62007/baggage/list/4
2015-07-22 17:25:43.953 ERROR 11308 --- [ XNIO-2 task-3] io.undertow.request : UT005023: Exception handling request to /flights/baggage/list/4
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 Not Found
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
Any idea ?
Thanks,
ray.
Your code looks backwards to me.
The feign client for the baggage service should be declared in the flight service and the baggage service should have a controller that responds on the URL you map in your baggage service client, you should not implement the interface annotated with #FeignClient.
The setup you have now will not have any controller listening on /baggage/list/{flightId} in the baggage service and no Feign client in flight service - the whole point of Feign is to call methods on an interface instead of manually handling URLs, Spring Cloud takes care of auto-instantiating the interface implementation and will use Eureka for discovery.
Try this (or modify so it fits your real world app):
Flight Service:
FlightIntegrationService.java:
#Component
public class FlightIntegrationService {
#Autowired
BaggageService baggageService;
public String getBaggageListById(String id) {
return baggageService.getBaggageListByFlightId(id);
}
}
BaggageService.java:
#FeignClient("baggage-service")
public interface BaggageService {
#RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
List<String> getBaggageListByFlightId(#PathVariable("flight_id") String flightId);
}
Baggage Service:
BaggageController.java:
#RestController
public class BaggageController {
#RequestMapping("/baggage/list/{flightId}")
public List<String> getBaggageListByFlightId(#PathVariable String flightId) {
return Arrays.asList("2,3,4");
}
}
Remove BaggageService.java and BaggageServiceImpl.java from the Baggage Service
registryService.getServiceUrl("baggage-service", ... replace with
registryService.getServiceUrl("baggage-service")
make sure that matches the right name
remove the localhost part
or only use the http://local part
It only worked for us if you have just the name of the service listed in eureka dashboard, not both

Resources