For example 500 Internal Server could imply that the apache server
internally has some permission issue.
Not necessarily. Uncached errors in the server-side application will cause the java server to return a "controlled" error 500.
From the web client point of view, 500 means:
-Something went wrong (somewhere) on the server-side. We don't know what. Don't retry the request-
For everything, a 200 should be returned by the application code.
The catalogue of status code is wider, but 200 is basically the default code to say: Ok, everything went fine. I encourage you to look at the 2xx status code list to enrich server-client the communication.
For example, if any exception is thrown within a service method then a
500 is returned to the client. Is the HTTP response convention broken
by Spring?
That's ok. When application errors reach the application server, the server catches them and does return the only reasonable error for uncontrolled errors. 500.
In that case, because an exception might be thrown by application
code, shouldn't a 200 status code be returned?
That would be read in this way:
--the request successfully failed--
From the communication point of view, it doesn't seem to me effective. Usually, 5xx error codes mean: Try it much later, while 4xx codes mean: Try it again but, this time, do it well. Returning a 2xx code when the request didn't finish successfully. What are we communicating to the client?
We might argue that the text message will tell the user what to do, despite de https status code but, what happens if there's no user? How would you programme a machine-to-machine communication if every call ends "successfully"? Matching strings? Declaring custom status codes? Wouldn't that add unnecessary complexity?
Should the application code catch the error, return a 200 status code
and add a more business/application specific message.
Depends. If you want your application to be a good www citizen then no, you should not. It's good for web applications to make a proper usage of the architecture web. So, if you need to communicate an error (5xx, 4xx) alongside with a specific error message, then do It. Tell to the web client: the request has not been processed due to the following errors
Let's say the application database is having issues? Or is it OK to
return the 500 message?
It's ok, For this specific case, a 500 status code make sense. But, ultimately, depends on the requirements and your preferences. If you are concerned about how to manage the error handling with Spring web, it might interest the following links 1 or 2.