I'm trying to catch the error this error message from my Rest controller in spring
#GetMapping
public List<Student> getAllStudent() {
throw new IllegalStateException("Opps can not get all students");
// return studentService.getAllStudents();
}
The error is catch in react this way, what I'm trying to do is to show in the console the Error message
import fetch from "unfetch";
const checkStatus = (response) => {
if (response.ok) {
return response;
} else {
let error = new Error(response.statusText);
error.response = response;
response.json().then((e) => {
error.error = e;
});
return Promise.reject(error);
}
};
export const getAllStudents = () =>
fetch("http://localhost:1020/api/students").then(checkStatus);
And then is consume by this method to show it in the console
const fetchAllStudents = () => {
this.setState({
isFetching: true,
});
getAllStudents()
.then((res) =>
res.json().then((students) => {
console.log(students);
this.setState({
students,
isFetching: false,
});
})
)
.catch((error) => {
console.log(error.error.message);
// const message =error.error.message;
// errorNotification(message,message)
this.setState({
isFetching: false,
});
});
};
The problem is that I get is that "message" is undefined I want to log "Opps can not get all students" in the console:
Add this line to your application.properties file:
server.error.include-message=always
And try throwing ResponseStatusException, so that you give a HTTP Status, together with the message, and not just 500 Server Error.
Like this:
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Your Message...");
Related
I try to explain the problem.in App.js I have Function getUser .when call this function.in first request get 401 error . For this reason in axios.interceptors.response I receive error 401.At this time, I receive a token and repeat my request again.And it is done successfully.But not return response in Function getUser.
I have hook for authentication and send request.
import React from "react";
import axios from "axios";
const API_URL = "http://127.0.0.1:4000/api/";
function useJWT() {
axios.interceptors.request.use(
(request) => {
request.headers.common["Accept"] = "application/json";
console.log("request Send ");
return request;
},
(error) => {
return Promise.reject(error);
}
);
axios.interceptors.response.use(
(response) => {
console.log("answer = ", response);
return response;
},
(error) => {
if (error?.response?.status) {
switch (error.response.status) {
case 401:
refreshToken().then((responseTwo) => {
return
sendPostRequest(
error.response.config.url
.split("/")
.findLast((item) => true)
.toString(),
error.response.config.data
);
});
break;
case 500:
// Actions for Error 500
throw error;
default:
console.error("from hook interceptor => ", error);
throw error;
}
} else {
// Occurs for axios error.message = 'Network Error'
throw error;
}
}
);
const refreshToken = () => {
const token = localStorage.getItem("refresh");
return axios
.post(API_URL + "token", {
token,
})
.then((response) => {
if (response.data.access) {
localStorage.setItem("access", response.data.access);
}
if (response.data.refresh) {
localStorage.setItem("refresh", response.data.refresh);
}
return response.data;
});
};
function login(email, password) {
return axios
.post(API_URL + "login", {
email,
password,
})
.then((response) => {
if (response.data.access) {
localStorage.setItem("access", response.data.access);
}
if (response.data.refresh) {
localStorage.setItem("refresh", response.data.refresh);
}
return response.data;
});
}
const sendPostRequest = (url, data) => {
console.log(300);
const token = localStorage.getItem("access");
axios.defaults.headers.common["jwt"] = token;
return axios.post(API_URL + url, {
data,
});
};
const logout = () => {
const token = localStorage.getItem("refresh");
return axios
.delete(API_URL + "logout", {
token,
})
.then((response) => {
localStorage.removeItem("access");
localStorage.removeItem("refresh");
});
};
return {
login,
logout,
refreshToken,
sendPostRequest,
};
}
export default useJWT;
In App.js ,I want to repeat the same request again if a 401 error is issued when I read the user information.
The request is successfully repeated but does not return the value.
When first request fail response is return equals null . and in catch when receive 401 error i am send second request but not return response.
I send request below code .
const getUser = () => {
console.log(12);
return sendPostRequest("user");
};
useEffect(() => {
let token = localStorage.getItem("access");
console.log("token = ", token);
if (token != null) {
//Here I have done simulation for 401 error
localStorage.setItem("access", "");
getUser()
.then((response) => {
console.log("response 1= ", response);
})
.catch((exception) => {
console.log("exception = ", exception.toString());
})
.then((response) => {
console.log("response 2= ", response);
});
} else {
navigate("/login");
}
}, []);
Best regards.
I didn't fully understand what exactly you want to do here.
But if you are looking to retry when 401 happens, you could use axios-retry to do it for you.
I'll pass the basics, but you can look more into what this does.
// First you need to create an axios instance
const axiosClient = axios.create({
baseURL: 'API_URL',
// not needed
timeout: 30000
});
// Then you need to add this to the axiosRetry lib
axiosRetry(axiosClient, {
retries: 3,
// Doesn't need to be this, it can be a number in ms
retryDelay: axiosRetry.exponentialDelay,
retryCondition: (error) => {
// You could do this way or try to implement your own
return error.response.status > 400
// something like this works too.
// error.response.status === 401 || error.response.status >= 500;
}
});
Just like in your code, we need to use interceptors if you want to avoid breaking your page, otherwise you can use try catch to catch any errors that may happen in a request.
// It could be something like this, like I said, it's not really needed.
axiosClient.interceptors.response.use(
(success) => success,
(err) => err
);
And finally, you could use the axiosClient directly since it now has your API_URL, calling it like this axiosClient.post('/user').
More or less that's it, you should just debug this code and see what is causing the return value to be null.
I would change these then/catch to be an async/await function, it would be more readable making your debugging easier.
axios-retry example if you didn't understand my explanation.
I find anwser for this question.
When error 401 occurs then create new Promise
I Wrote this code.
case 401:
return new Promise((resolve, reject) => {
refreshToken().then((responseTwo) => {
resolve(
sendPostRequest(
error.response.config.url
.split("/")
.findLast((item) => true)
.toString(),
error.response.config.data
)
);
});
});
I do an axios get(url + this.state.user) but the parameter is undefined for no reason because when i do a console log of the parameter it exists...
My code
state = {
user: [],
taches : [],
loading: false
}
componentDidMount = () => {
this.setState({loading:true})
axios.get('/get-user').then(response => {
this.setState({user : response.data});
}).catch(error => {
console.log(error);
})
axios.get('/get-taches/' + this.state.user.ID_Users).then(response => {
console.log(this.state.user.ID_Users);
}).catch(error => {
console.log(this.state.user.ID_Users);
console.log(error);
})
}
The parameter of axios get-taches return undefined but when i do a console log of it in the catch error it is defined and it shows in the console... I dont know where the problem is.
Thank you for your help
Error handling middleware in node js backend:
app.use((error, req, res, next) => {
console.log(error);
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
I have the following try catch block from my app:
userLogin() {
//axios vue instance
this.$http
.post("/auth/signup", this.formData)
.then((res) => {
// res.status == 201 ? (this.formData = {}) : "";
console.log(res);
})
.catch((err) => {
console.log(err);
console.log(err.data.data);
console.log(err.data.msg);
});
},
The output of the above catch block are as follows:
[![enter image description here][2]][2]
While my rest api sends the message in following format (seen on Network > Preview)
{
message: "Validation failed.",
…
}
data: [{
location: "body",
param: "email",
value: "test#test.com",
msg: "E-Mail address already exists!"
}]
message: "Validation failed."
I want to access the data array and print its content.
How can I access data ?
We can catch custom error message:
userLogin() {
this.$http
.post("/auth/signup", this.formData)
.then((res) => {
// res.status == 201 ? (this.formData = {}) : "";
console.log(res);
})
.catch((err) => {
console.log(err.response.data.data);
});
},
Axios stores the actual response in its data prop (unrelated to your API's data property in the response contents), so you could access your data property like this:
this.$http.post('/auth/signup', this.formData)
.then((res) => {
const apiResponse = res.data
console.log(apiResponse.data) // logs `data` property from API response contents
})
.catch((err) => {
/*...*/
})
More readable format
async userLogin() {
try {
// Call the server
const {data} = await this.$http.post("/auth/signup", this.formData);
// If you want message
let message = data.message;
// If you want the data object, ex data: [{location: "body"....}]
let dataObject = data.data;
} catch (e) {
// In case of error
console.log(err.response);
}
};
Here i have my component code for SignIng Up user and check for Error. At first error is null.
let error = useSelector((state) => state.authReducer.error);
const checkErrorLoading = () => {
console.log("If error found"); //At first it gives null, but on backend there is error
toast.error(error);
console.log(loading, error);
};
const handleSubmit = async (e) => {
if (isSignup) {
dispatch(signup(form, history));
checkErrorLoading();
} else {
dispatch(signin(form, history));
checkErrorLoading();
}
};
Now at my singupForm, i provide wrong input or wrong data. The backend gives me error that is completely fine.
ISSUE => But when i click on Login button. At first attempt it does not provide any error message. After second attempt it works fine, but not at first attempt. At first attempt it gives me Error value NULL while there is still an error
Here is my action.
export const signup = (formData, history) => async (dispatch) => {
try {
const res = await api.signUp(formData);
dispatch({ type: authConstants.AUTH_REQUEST });
if (res.status === 200) {
const { data } = res;
console.log(data);
dispatch({
type: authConstants.AUTH_SUCCESS,
payload: data,
});
}
console.log(res.status);
history.push("/");
} catch (error) {
console.log(error.response);
dispatch({
type: authConstants.AUTH_FAILURE,
payload: error.response.data.error,
});
}
};
and than reducer.
const initialState = {
authData: null,
error: null,
loading: false,
};
const authReducer = (state = initialState, action) => {
switch (action.type) {
case authConstants.AUTH_REQUEST:
return { ...state, loading: true, error: null };
case authConstants.AUTH_SUCCESS:
localStorage.setItem("profile", JSON.stringify({ ...action?.payload }));
return { ...state, authData: action?.data, loading: false, error: null };
case authConstants.AUTH_FAILURE:
console.log(action.payload);
return { ...state, loading: false, error: action.payload };
}
You should use useEffect instead of local function (checkErrorLoading ) for such cases:
useEffect(() => {
console.log("If error found");
toast.error(error);
console.log(loading, error);
},[error]);
Currently what you doing is creating local function that closures error variable, which initially is null + state is updated asynchronously, so you cannot execute function right after dispatching (even if variable wouldn't be closured, you will not have fresh state there)
I tried to delete the item >>But when I click on the button and function does not work!!!!
Deleting in backend works but in frontend does not work!!
This is my function:
deleteblog = async id => {
// this.setState({ isLoading: true });
try {
const response = await fetch(
`http://localhost:8080/blog/delete/${id}`
);
const answer = await response.json();
if (answer.success) {
const blog = this.state.blog.filter(
contact => contact.id !== id
);
toast(`blog with id ${id} was successfully deleted!`);
this.setState({ blog });
} else {
console.log();
false });
}
} catch (err) {
console.log("error", err);
false });
}
};
This is the button:
<button type="button" onClick={this.deleteblog} class="btn btn-danger btn-rounded btn-sm my-0">delete</button>
This error that is showed in console log
GET http://localhost:8080/blog/delete/undefined 500 (Internal Server Error)
error SyntaxError: Unexpected token < in JSON at position 0
at BlogAdmin.deleteblog (Blogadmin.js:104)
And this >>> Blogadmin.js:104
====> const answer = await response.json();
The response might be an HTML instead of a JSON response, it is better to have more check than accessing response.json() directly as that will be dangerous and easily throw you a Syntax Error.
You can check the response through the browser development console -> Network tab, and see the request and response:
or adding console.log to the response for debugging.
After all, you should improve the handling for reading the response data, and your application will be fine:
deleteblog = async id => {
this.setState({ isLoading: true });
try {
const response = await fetch(`http://localhost:8080/blog/delete/${id}`);
// For debugging
console.log('response', JSON.stringify(response));
const answer = response && typeof response.json === 'function' && response.json();
if (answer.success) {
const blog = this.state.blog.filter(contact => contact.id !== id);
toast(`blog with id ${id} was successfully deleted!`);
this.setState({ blog });
}
else {
toast(`Error: blog with id ${id} was unable to delete!`);
this.setState({ isLoading: false });
}
}
catch (err) {
console.error('Unexpected error occurred:', err);
this.setState({ isLoading: false });
}
};