I'm new to Spring Boot and I'm playing around with it trying to get a response from my backend.
The web server and application are running without errors but when I try to get "Hello World" by typing localhost:8080/api/hello I get a 404 not found.
This is the controller method
#RestController
#RequestMapping("/api")
public class EmployeeController {
#GetMapping("/hello")
public String greeting() {
return "Hello, World";
}
}
This is the response I get
the response
You've defined your api path as api/hello, but based on the screenshot of your request you are calling /hello.
use localhost:8080/api/hello ,
it will a solution for your problem
Related
I'm working on a full-stack app having spring boot v2.7.5 as the backend and Angular v15 as the front end. I use IntelliJ IDEA IDE for development. Locally, spring boot runs on http://localhost:8080 and angular runs on http://localhost:4200. I use Gradle to build the project a single war file and which would be deployed on an external tomcat server.
Following is the project structure:
I have 3 build.gradle files, 1 for frontend , 1 for backend, and 1 for global. When I run the global build.gradle file, it would call call build.gradle from fronend folder which builds angular project and copies all the build files and put them into backend/src/main/resources/static folder. Next, build.gradle from the backend gets called which would build the final war file to be deployed on the external tomcat server.
The reason I'm putting frontend build files (index.html, some .js files) into backend/src/main/resources/static is the fact that Spring Boot Serves static content from that location. more details .
So the static directory looks like this after adding frontend build files:
When I try to access http://localhost:8080, it loads index.html from the static folder.
So far it is good. When I click the login button, internally it calls the backend API and moves to the next page (home page i.e., http://localhost:8080/fe/appInstances).
Now if I refresh the page, it gives me the following 404 Whitelabel Error Page.
I understand that since this is spring-boot as it is looking for a definition of the http://localhost:8080/fe/appInstances API endpoint in the java code.
To fix this, I have created the following IndexController.java class which should redirect all the frontend rest endpoints to index.html which is present in main/resources/static folder.
IndexController.java
#Controller
public class IndexController {
#GetMapping("/")
public String index() {
return "redirect:/index";
}
#GetMapping("/fe/*")
public String anyFrontEndApi() {
return "index";
}
}
But now, I get the following Whitelabel error page about Circular view path [index]: would dispatch back to the current handler URL [/fe/index] again.
I have tried changing #Controller to #RestController and changing the return type to ModelandView or something like this. But irrespective of all, it is still giving me the Whitelabel Error Page about Circular view path...
#RestController
public class IndexController {
#GetMapping("/")
public String index() {
return "redirect:/index";
}
#GetMapping("/fe/*")
public ModelAndView anyFrontEndApi() {
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
return mv;
}
}
Am I missing something here? Can someone please suggest me a fix for this?
PS: #justthink addressed this situation here. But I don't know how to do reverse proxy way.
We had this situation of page refresh for Angular and Springboot and we resolved this by adding the below Configuration class extending WebMvcConfigurerAdapter
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**/*")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/index.html");
}
});
}
}
So basically, we are telling Springboot that if we have the resource, use the same if not then redirect it to index.html.
Now, to handle the path in Angular, it depends on how you would have written your routes. If the path is available, you show the page, if not, display 404 page.
Hope this helps.
Update 1:
WebMvcConfigurerAdapter is deprecated. If this causes any trouble, then instead of extending the class WebMvcConfigurerAdapter, you can implement WebMvcConfigurer
If you see the whitelabel error says that "this application has no explicit mapping for /error".
That means if no path is matched with the paths that are defined in controller mappings, it forwards the request to "/error" route. So we can override this default behaviour.
Spring provides ErrorController interface to override this functionality
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class CustomErrorController implements ErrorController {
#RequestMapping("/error")
public String handleError() {
return "forward:/";
}
}
I use React for fronted + Java Spring controllers that have some endpoints for backend. But for some of endpoints I have response with React features and for some without React features. I am new with React part, so I suppose that I am missing some principles of fetch(). Please help me to understand and fix.
Case 1
App.js code:
import React, {useState, useEffect} from 'react';
import './App.css';
function App () {
const [message, setMessage] = useState("");
useEffect(() => {
fetch('http://localhost:8080/api/v1/hello')
.then(response => response.text())
.then(message => {
setMessage(message);
});
},[])
return (
<div className="App">
<header className="">
<h1>React is here!</h1>
<h2 className="App-title">{message}</h2>
</header>
</div>
)
}
export default App;
Java controller code:
#RestController
#CrossOrigin
#RequestMapping(path = "/api/v1")
public class BasicController {
#GetMapping("/hello")
public String sayHello() {
return "Hello Everyone !";
}
}
As a result I see "React is here!" + "Hello Everyone !" with according style string on localhost:8080. So I see that the backend returns value and React also works with it.
But if I go to localhost:8080/api/v1/hello, I see only "Hello Everyone !" string without React features. So the backend returns value, but React doesn't work.
Why, if I am fetching this particular endpoint? - Question 1
Actually, the same result if I use
#RequestMapping(path = "api/v1")
without the first /
Case 2
I have the same App.js but change fetch(URL) to
fetch('http://localhost:8080')
And I add a new Controller:
#RestController
#CrossOrigin
#RequestMapping(path = "/")
public class StartPageController {
#GetMapping()
public String startPage() {
return "Start page";
}
}
If I go to localhost:8080, that I am fetching I see only "Start page" string without React features. So the backend returns value, but React doesn't work.
Why, if it is the simplest option for endpoint path and even more complex fetch worked as I mentioned above? - Question 2
Case 3
As it seems that I have some issue with "/" endpoint, I decided to check how the Case 1 endpoint will work if I leave StartPageController from the Case 2. So I just return back url:
fetch('http://localhost:8080/api/v1/hello'),
but leave both controllers.
As a result, for now, I see that React features doesn't work either for localhost:8080, or localhost:8080/api/v1/hello (the last one actually as in Case 1). Only backend values "Start page" or "Hello Everyone !" return for all mentioned endpoints. Without React.
So it seems that the "/" endpoint from StartPageController doesn't work with React by itself and also doesn't allow to work other more complex endpoints as a root endpoint.
So 2 questions as a result:
What is the issue with some particular paths - Case 1?
What is the issue with "/" endpoint - Case 2 and 3?
How I run Spring boot + React - I make a .jar file by Maven, where I collect both parts for frontend and backend by .pom build configurations. And I run the .jar in Intellij IDEA. I need to do it this way because I want to deploy .jar later on AWS Elastic Beanstalk.
Let's understand this code first :
#RestController
#CrossOrigin
#RequestMapping(path = "/api/v1")
public class BasicController {
#GetMapping("/hello")
public String sayHello() {
return "Hello Everyone !";
}
}
Probably your backend server is running at port 8080 and if you hit this url localhost:8080/api/v1/hello , it gives the output as "Hello Everyone" which you've returned from the controller right ? How do you expect to get React Part when you hit this endpoint ? When you run localhost:8080/api/v1/hello this is Spring Part [Java part] and not the react part. If you use this endpoint from the react app or any client you'll always get "Hello Everyone" as per your logic, same applies for the StartPage controller as well.
Try to run your react application, if you're fetching correctly, you'll see the backend part used with front end part. It's as simple as that.
See which port the react application is using ? It's probably localhost:3000 see if it's working or not. There, you'll see the result.
Hope this helps :)
I hava Spring Boot Application.I want to show html.
index.html location is following
templete/view/index.html
Controller.java
#Controller
public class Controller {
#RequestMapping(value = "/view", method = RequestMethod.GET)
public String index() {
return "/view/index.html";
}
}
return "view/index";
Should be what you need. In the future you might consider saying what you expect to happen and what actually happens, even better providing an error message which might give a hint like your file could not be found.
I do have a react-application using BrowserRouter for routing between pages. I also have a Java Backend with Spring Boot.
When I start the backend and frontend seperataly with an applicationRunner and npm start the browserrouter works perfectly. For example http://localhost:3000/home works fine. And also localhost:8080/api/collection/{id} works fine with this code
Java-backend:
#RestController
#RequestMapping(value = "/api", produces = MediaType.APPLICATION_JSON_VALUE)
public class ApiController {
#Autowired
private BeregningstjenestePoller poller;
#GetMapping("/collection/{id}")
public CollectionV2 withId(#PathVariable String id) {
return poller.getCollectionWithId(id);
}
React-frontend:
<BrowserRouter>
<Route exact path={'/'}>
<StartPage title={'Hello'} />
</Route>
<Route exact path={'/home'}>
<HomePage />
</Route>
</BrowserRouter>
But when I try to start the servers together with java -jar ./bapplication-main/target/beregning-oversikt-main-0-SNAPSHOT.jar the trouble starts.
The application is now running on localhost:8080, so the starting page works, but localhost:8080/home doesnt work anymore, but localhost:8080/api/collection/{id} still works.
My guess is some trouble with Spring Boot and React routing together, but I cant find an answer
Might the Route "/" is defined in both reactjs and spring boot.
So remove index method with "/" in spring boot IndexController, below method need to be removed.. it will work with React home page.
#Controller
public class IndexController {
#GetMapping("/")
public String index(Model model) {
return "index";
}
}
I am making small application. I think I made everything correctly but I got 404 error. Please be honest and see my code https://github.com/chalauri/Tsu_Junior and tell me if anything is incorrect. I deployed my application on tomcat. the module path is "/" and for example I got 404 http://localhost:8080/tsu/faculty/test from this url
One issue I see (but probably not the only one); It looks like you are trying to access a method in the FacultyResource class, but there is no method with a path of test or a path parameter in that class.
Try adding a method with path test
#Path("/test")
#GET
public String testMethod(){
return "Hello World";
}
Or add a method with a path param
#Path("/{name}")
#GET
public String testMethod(#PathParam("name") String name){
return "Hello " + name;
}