Java Spring controller fetching from React fetch() - java

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

Related

CORS Policy Blocking Java Spring API Request calling from React using axios

I have a gateway with some APIs developed with Java Spring boot. But when I am calling the APIs from my react project the below error is thrown.
Access to XMLHttpRequest at 'http://localhost:8081/testgw/hello' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have added the #CrossOrigin annotation to my rest controller as below.
#CrossOrigin(origins= {"*"}, maxAge = 4800, allowCredentials = "false" )
#RestController
public class FTController {
#GetMapping("/hello")
public String getHello() {
return "Hello World!";
}
}
And I am calling the API from my react project as below
var url = "http://localhost:8081/testgw/hello";
axios.get(url, {
headers: {
'Authorization' : 'Basic [AuthKey]',
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'GET,POST,OPTIONS,DELETE,PUT'
}
})
.then(
function(response) {
console.log("response --> " + response);
}).catch(function(error) {
console.log(error);
}
);
I am not getting rid of this problem. Please let me know what should I do to solve this.
After a lots of struggling I am able to get rid of this issue. Generally adding the #CrossOrigin annotation over the REST controller class the request methods should fix the issue.
But if adding the annotation doesn't solve the issue then it's generating from your browser. In that case you can overcome the issue by running the browser disabling the web security.
For windows you can run goggle chrome disabling the web security by following the below steps
Open run (Press Window Key + R)
Write the below command
chrome.exe --user-data-dir="C://Chrome dev session" --disable-web-security
Press Enter

Getting the 307 Redirection Response instead of the target-location page content from an enpoint in Spring Boot

So I have a simple endpoint in my Spring Boot App, which just redirects to another website:
#Controller
public class FeedbackController {
#GetMapping(path = "/test")
public Mono<ResponseEntity<Void>> method() {
String redirectUrl = "https://www.google.com";
return Mono
.just(ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT).location(URI.create(redirectUrl)).build());
}
Making a GET request to this endpoint (e.g. in browser or with postman) gives me the page content of google as a response. However for testing purposes I want to make sure that the response is a TEMPORARY_REDIRECT with www.google.com as the Location Header.
How can I make a request to this endpoint so that the response is the 307 TEMPORARY_REDIRECT instead of the 200 with page content from the target website?
First
to test if its working, you could use simple tools like curl :
We add the -L flag to tell curl that we want to know if we are getting redirected
curl -L http://www.....
Go further
Then, you could simply use tools like MockMvc to automate this test
See this SO post

Spring boot controller mapping to react component

I am switching routes in my react app using -
<Route path="/myBootDomain" render={props => {
//check route path
const onpathA = window.location.href.indexOf('/pathA') !== -1;
const onpathB = window.location.href.indexOf('/pathB') !== -1;
if (onpathA){ return <PathAComponent />;}
else if(onpathB){ return <onpathBComponent />;}
}}/>
When I run the app on localhost it works as expected, so I want my controllers to map the subdomain's to the correct route, example controller -
#CrossOrigin(maxAge = 3600)
#RestController
#RequestMapping("/pathA")
public class WebContentController {
#RequestMapping(method = RequestMethod.GET)
public void method(HttpServletRequest request, HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader("Location", "/myBootDomain/pathA");
httpServletResponse.setStatus(302);
}
}
When trying to access http://localhost:8080/myBootDomain/pathA instead of redirecting to the index file I got redirected to the same controller(infinite loop).
My index.html is under /resources/static.
Thank for any help.
What you want to do is to serve same index.html file that contains scripts (React app) but from different paths, ie: /myBootDomain/pathA and /myBootDomain/pathA/foo/bar. It'll make sure that when user reloads the URL he gets the same React app which then executes routing logic. See #tashkhisi answer to get more context https://stackoverflow.com/a/62193394/906265
Now it depends how the server app is set up and which paths you want to make "catch-all" but there was a similar question already Spring catch all route for index.html
The way React works with route is different from something you might have worked before with server side frameworks like JSF, PrimeFaces and other simmilar frameworks.
Generally in React all routing is handled in client side(at least it should be done this way) and this approach is called single page application because you have one page in which components will be changed based on the route you have in client side and those components communicate with server and changed their content based on response they are delivered with server. Here you are handling your routing in client side with <Route> Component and in browser when path changed to /pathA, PathAComponent will be rendered and no request is sent to the server in this situation because React is controlling everything here). You should design your PathAComponent in such a way when it is rendered it call your method in the backend with Http Rest call and do something based on the response (for instance show status code of response to user).
check this link for further discussion
the more clear way to do something you want to do is shown bellow:
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route path='/pathA' exact={true} component={PathAComponent}/>
<Route path='/pathB' exact={true} component={PathBComponent}/>
</Switch>
</Router>
)
}
}
here when path change to /pathA in client side PathAComponent will be rendered and when path changed to /pathB component PathBComponent will be rendered. no request send to server up to this point to communicate with server you should call your REST api directly in your PathAComponent and PathBComponent, generally in componentDidMount method of your components.
class PathAComponent extends Component {
constructor(props) {
super(props);
this.state = {status: false, isLoading: true};
}
componentDidMount() {
this.setState({isLoading: true});
fetch('/myBootDomain/pathA')
.then(response => this.setState({status: response.status, isLoading: false}));
}
render() {
return (
<div>
statusCode: {status}
</div>
);
}
}

SpringMVC check server is UP or DOWN

How can I check if my server is UP or DOWN in SpringMVC or just simple in JAVA?
I want a simple function how receiving a URL as a parameter and return just one boolean variable TRUE or FALSE which represents a SERVER.
#RestController
public class HealthCheckController {
#RequestMapping("/healthcheck")
public Greeting greeting() {
return "up";
}
}
When you have to check if the server is up just send get request to /healthcheck. If it returns "up", you're OK.
If you use Spring Boot, you can take a look at actuator. It allows this functionality out of the box plus some other stuff like datasource checking and so on

Play framework: redirect to a different domain

I am using Play 2 with Java and one of my controller methods returns a redirect:
return redirect(<some other domain>);
The client side call happens from an angular controller through $http:
$http.get("/signin").
...
This does not work; Firefox tells me to enable CORS. So I tried to enable CORS as suggested by the answers to this StackOverflow question. But I still get the same error. However that answer seems to be directed towards JSON responses. Do I need to do anything different for a redirect?
I would have thought that setting Access-Control-Allow-Origin to * would do the trick, but that doesn't seem to work.
Http 3xx redirection responses are transparent to AJAX calls. One possible solution for this problem is to return something else than 303 which can be resolved by AJAX. For example you can assume that all responses from your application with code 280 are intended for an AJAX redirection. Then your controller would look like this:
public class Application extends Controller {
public static Result signin() {
// ...
return status(280, "https://api.twitter.com/oauth/authenticate?oauth_token=" + requestToken.getToken());
}
}
On the client side you could check a result status code and react for code 280. Below there's a simple example with a page redirect but you can do anything you like with that response.
<script>
$(function() {
$.ajax({'url': '/signin', statusCode: {
280: function(response) {
window.location = response;
}
}});
});
</script>

Categories

Resources