3 ExceptionHandling&Mapper
3 ExceptionHandling&Mapper
4. javax.ws.rs.WebApplicationException:
Approach-1: Throwing User-Exception Normally:
@Path("/card")
public class CardAgent {
// Applying for Credit Card
@POST
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
@Path("/apply/{bank}/{uuid}")
public Response applyCard(InputStream is,
@PathParam("bank") String bankName,
@PathParam("uuid") String uuid) {
// validate logic
if (bankName.equals("icici") && uuid.equals("C1")) {
throw new CardAlreadyIssuedException("Already User has been issued the
card");
}
return Response.ok().build();
}
}
Access the application:
http://localhost:8083/3.1ThrowingUserExceptionNormally/rest/card/apply/icici/C1
Select POST
Content-Type: application/xml
Send some dummy xml to test
<card></card>
Response:
500: Internal Server Error
Stacktrace as error details in body which cannot be understand by the client.
Observe at server console:
com.wae.exception.CardAlreadyIssuedException: Already User has been issued the
card.
That means if we throw user Exception normally JAX-RS Runtime will sends back to
the client as 505 Internal Server Error which client cannot understand.
return Response.status(409)
.entity("<error><error-code>409</error-code><message>Card
Already Issued</message></error>").build();
// In this Approach code readability will not be there bcz exception is looks like
response so we cannot code properly.
}
return Response.ok().build();
}
}
Access the application:
http://localhost:8083/3.2SendExceptionDetailsUsingResponse/rest/card/apply/icici/
C1
Select POST
Content-Type: application/xml
Send some dummy xml to test
<card></card>
Response:
Status code : 409 Conflict (Which we given)
Error details as Response:
<error>
<error-code>409</error-code>
<message>Card Already Issued</message>
</error>
Observe at server console:
Nothing will be there in the server console bcz we modelled exception details as
Response so that it send Exception as error details using Response obj.
This approach gives response with appropriate status code that we given and error
details to the client but it will not gives readability to the developers whether it is
exception response or normal response. Hence it not recommend to use. That is the
reason JAX-RS has provided WebApplicationException.
Purpose of WebApplicationException:
Instead of throwing our exception normally or returning status codes and error details
as normal responses directly, JAX-RS has provided one exception called as
WebApplicationException which we can throw directly by populating with proper
response code, with proper error message using Response. So that for the developer
code readability will be more bcz we are throwing exception with proper error details
using Response.
The JAX-RS API has a built in unchecked exception called as WebApplicationException
that applications can throw. We can pre-initialized this exception with either a
Response or a particular status code by using methods that JAX-RS has provided which
are given below.
public class WebApplicationException extends RuntimeException {
public WebApplicationException() {...}
public WebApplicationException(Response response) {...}
public WebApplicationException(int status) {...}
public WebApplicationException(Response.Status status) {...}
public WebApplicationException(Throwable cause) {...}
public WebApplicationException(Throwable cause,
Response response) {...}
public WebApplicationException(Throwable cause, int status) {...}
public WebApplicationException(Throwable cause,
Response.Status status) {...}
public Response getResponse() {...}
}
When JAX-RS sees that a WebApplicationException has been thrown by application
code, it catches the exception and calls its getResponse() method to obtain a Response
to send back to the client. If the application has initialized the
WebApplicationException with a status code or Response object, that code or
Response will be used to create the actual HTTP response. Otherwise, the
WebApplicationException will return a status code of 500, "Internal Server Error" to
the client.
Approach-3: WebApplicationException
For example, let’s say we have a web service that allows clients to apply for credit
cards details represented in XML:
@Path("/card")
class CardAgent {
// Applying for Credit Card
@POST
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
@Path("/apply/{bank}/{uuid}")
public Response applyCard(InputStream is,
@PathParam("bank") String bankName,
@PathParam("uuid") String uuid) {
// To check various possibilities, comment one by one case
/**
* If we wanted to Wrap/convert one exception to another exception then
* only we need here try catch otherwise not required to take try-catch
* bcz JAX-RS will handles the exception if we wrap our exception to
* WebApplicationException. If we don't want to wrap then not required
* try-catch rather we can throw directly and declare to throws bcz it
* is Checked-Exception.
*/
try {
// Here we are throwing exception to observe the o/p but in reality
// service layer validator classes will throws exception
if (bankName.equals("icici") && uuid.equals("C1")) {
throw new CardAlreadyIssuedException("Already User has been issued the
card");
}
} catch (CardAlreadyIssuedException e) {
// Actually in entity() method we need to return JAXB obj which
// contains error details as obj
// Status.CONFLICT indicates status code as 409 already exists
try {
// Here we are throwing exception to observe the o/p but in reality
// service layer validator classes will throws exception
if (bankName.equals("icici") && uuid.equals("C1")) {
throw new CardAlreadyIssuedRuntimeException("Already User has been issued
the card");
}
} catch (CardAlreadyIssuedRuntimeException e) {
// Actually in entity() method we need to return JAXB obj which
// contains error details as obj
throw new WebApplicationException(Response.status(Status.CONFLICT)
.entity("<error><error-code>409</error-code><message>Card Already
Issued(Using Case:3)</message></error>").build());
}
return Response.ok().build();
}
}
Access the application:
Case: 1
http://localhost:8083/3.3WebApplException/rest/card/apply/icici/C1
Select POST
Content-Type: application/xml
Send the some dummy xml to test
<card></card>
Response:
Status code : 409 Conflict (Which we given)
Observe Error details as Response:
<error>
<error-code>409</error-code>
<message>Card Already Issued(Using Case: 1)</message>
</error>
Observe at server console:
Nothing will be there in the server console bcz we modelled exception details as
Response so that it send Exception as error details using Response obj and if we
wanted to see the exception then we can take try-catch to printStackTrace() and to
log then again throw it but not required unless we wanted to see the to do logging.
Case: 2
http://localhost:8083/3.3WebApplException/rest/card/apply/icici/C1
Select POST
Content-Type: application/xml
Send the some dummy xml to test
<card></card>
Response:
Status code : 409 Conflict (Which we given)
Observe Error details as Response:
<error>
<error-code>409</error-code>
<message>Card Already Issued(Using Case: 1)</message>
</error>
Case: 3
http://localhost:8083/3.3WebApplException/rest/card/apply/icici/C1
Select POST
Content-Type: application/xml
Send the some dummy xml to test
<card></card>
Response:
Status code : 409 Conflict (Which we given)
Observe Error details as Response:
<error>
<error-code>409</error-code>
<message>Card Already Issued(Using Case: 1)</message>
</error>
Observation:
This WebApplication approach (which contains 3-cases) will gives more readability
about the code bcz we throwing exception which contains response as error details,
but in previous approach error details also as like normal response so it will not gives
readability to the developers whether it is exception response or normal response. But
if we use WebApplication exception which allows us to build errors as response so that
we can model a error details as response so that readability will be more bcz we are
throwing exception (but not returning just as response) which contains error details
as response.
5. Practical difference between Web Services and RESTful services:
1. We cannot model a REST Resource with 2-objects like Order and Address bcz body
will contains only 1-XML so as we cannot sent multiple XML's as part of request body
we cannot take multiple obj's as params but we can take Order and Address both in
a single obj called as PurchaseOrder so that we can get both obj's in a single XML.
@Path("/order")
class OrderResource {
@POST
@Path(("/new")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Response newOrder(PurchaseOrder purchaseOrder) {
}
}
<purchaseOrder>
<order>
<orderId>929292<orderId>
<productName>LCD TV<productName>
<order>
<address>
....
</address>
< /purchaseOrder>
2. In Web Services we can use soap: faults to build the error response back to the
consumer but in REST we communicate back to the client using status codes.
Can we model a REST Resource which will takes 2-obj's as parameters?
Ans:
No, We cannot model REST Resource with obj's as parameters bcz we cannot send 2-
xml's in a single body. So if we want 2-obj's then wrap those obj's in a single obj and
model it. Similarly we cannot model using 2-Inputstream's or 2-char[] etc as 2-
parameters rather we need to take only one param.
What is the practical difference between Web Services and RESTful services that
you have observe while working?
Ans:
In REST we can never model a Resource taking 2-parameters but in Web Services it
can be possible.
@Path("/card-payer")
public class CardPayer {
// We have Bank Account but we don't have credit card but we are trying to pay the
money for online shopping throw online via with wrong credit cardNo.
@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/pay/{card}")
public Response payAmount(@PathParam("card") String cardNo) {
try {
// service layer will checks the valid card or not and throws exception if not valid,
if valid card then process the payment
if (cardNo.equals("C2")) {
throw new CardNotFoundException();
}
} catch (CardNotFoundException e) {
throw new WebApplicationException(Response.status(Status.NOT_FOUND)
.entity("<error><error-code>400</error-code><message>With Entered
cardNo there is no CardDetails to display so plz apply for the Credit Card
</message></error>").build());
}
return Response.ok().build();
}
}
@Provider
public class EntityNotFoundMapper implements
ExceptionMapper<EntityNotFoundException> {
public Response toResponse(EntityNotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
Similarly we can write our Exception as CardNotFoundException and we can map our
Exception with ExceptionMapper so that whenever we throw the
CardNotFoundException JAX-RS Runtime will build the error response and takes that
response and sendback to the client so we no need to duplicate the error with status
codes in all the Resource classes, rather we need to just throw exception from our
Resource class.
@Provider
public class CardNotFoundExceptionMapper implements
ExceptionMapper<CardNotFoundException> {
public Response toResponse(CardNotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
Our ExceptionMapper implementation must be annotated with the @Provider
annotation. This tells the JAX-RS runtime that it is a component. The class
implementing the ExceptionMapper interface must provide the parameterized type of
the ExceptionMapper. JAX-RS uses this generic type information to match up thrown
exceptions to ExceptionMappers. Finally, the toResponse() method receives the
thrown exception and creates a Response object that will be used to build the HTTP
response.
JAX-RS supports exception inheritance as well. When an exception is thrown, JAX-RS
will first try to find an ExceptionMapper for that exception’s type. If it cannot find one,
it will look for a mapper that can handle the exception’s superclass. It will continue
this process until there are no more super classes to match against.
Finally, ExceptionMappers are registered with the JAX-RS runtime using the
deployment APIs using @Provider annotation.
So by using ExceptionMapper we can rewrite the above Resource class as follows
without duplicating the error details in each and every Resource class. So if we use
Exception Mapper we no need to write try and catch rather simply we can throw the
exception so it will be received by the JAX-RS Runtime through the exception
propagation/delegation principle so it looks for the exception mapper and sends details
for the failure from the Mapper. If mapper is not there then it will sends default error
messages, but sending default error messages is not recommended hence we need to
use either WebApplicationException or ExceptionMapper and if we want to use same
exception in multiple places then use ExceptionMapper otherwise we can use
WebApplicationException.
Write Mappers:
@Provider
public class CardNotFoundExceptionMapper implements
ExceptionMapper<CardNotFoundException> {
@Override
public Response toResponse(CardNotFoundException cnfe) {
// NOT_FOUND indicates 400 status code
return Response.status(Status.NOT_FOUND)
.entity("<error><error-code>400</error-code><message>Entered card Not
registered to get the details plz apply for new Card</message></error>").build();
}
}
@Provider
public class CardNotFoundRuntimeExceptionMapper implements
ExceptionMapper<CardNotFoundRuntimeException> {
@Override
public Response toResponse(CardNotFoundRuntimeException rte) {
// NOT_FOUND indicates 400 status code
return Response.status(Status.NOT_FOUND)
.entity("<error><error-code>400</error-code><message>Entered card Not
registerd plz apply for new Debit Card</message></error>").build();
}
}
@Provider
public class WebApplicationExceptionMapper implements
ExceptionMapper<WebApplicationException> {
@Override
public Response toResponse(WebApplicationException rte) {
// NOT_FOUND indicates 400 status code
return Response.status(Status.NOT_FOUND)
.entity("<error><error-code>400</error-code><message>Entered card Not
registerd plz apply for new Credit Card</message></error>").build();
}
}
@Path("/card")
public class CardAgent {
// We have Bank Account but we don't have credit card but we are trying to
// get the credit card
// details with wrong cardNo which throws exception
@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/get/{card}")
public Response applyCreditCard(@PathParam("card") String cardNo)
throws CardNotFoundException {
// call the service layer so that service layer will throw this
// exception actually
CardAgentDao dao = new CardAgentDao();
String details = null;
@Path("/card-payer")
public class CardPayer {
// We have Bank Account but we don't have credit/debit card but we are
// trying to pay the money for online
// Approach-1
if (response == false) {
throw new WebApplicationException();
}
@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/debit/{card}")
public Response payAmountViaDebitCard(@PathParam("card") String cardNo) {
CardPayerDao dao = new CardPayerDao();
boolean response = dao.pay(cardNo);
if (response == false) {
throw new CardNotFoundRuntimeException(
"CardNotFound: Entered card not eligible for payment Plz apply for new Debit
Card");
}
http://localhost:8083/3.4ExceptionMapperForCheckedUncheckedWebApplExceptions
/rest/card-payer/credit/C2
Select GET
Content-Type: text/plain
Response:
<error>
<error-code>400</error-code>
<message>Entered card Not registerd plz apply for new Credit Card</message>
</error>
http://localhost:8083/3.4ExceptionMapperForCheckedUncheckedWebApplExceptions
/rest/card-payer/debit/C2
Select GET
Content-Type: text/plain
Response:
<error>
<error-code>400</error-code>
<message>Entered card Not registered plz apply for new Debit Card</message>
</error>
7. Sub exception classes of WebApplicationException:
JAX-RS 2.0 has added a nice exception hierarchy for various HTTP error conditions.
So, instead of creating an instance of WebApplicationException and initializing it with
a specific status code, we can use one of these exceptions instead. We can change
our previous example to use javax.ws.rs.NotFoundException:
@Path("/customers")
public class CustomerResource {
@GET
@Path("{id}")
@Produces("application/xml")
public Customer getCustomer(@PathParam("id") int id) {
Customer cust = findCustomer(id);
if (cust == null) {
throw new NotFoundException());
}
return cust;
}
}
Like the other exceptions in the exception hierarchy, NotFoundException inherits from
WebApplicationException. If we looked at the code, we can see that in its constructor
it is initializing the status code to be 404.
The below given Table lists some other exceptions we can use for error conditions that
are under the javax.ws.rs package.
BadRequestException is used when the client sends something to the server that the
server cannot interpret. The JAX-RS runtime will actually throw this exception in
certain scenarios. The most obvious is when a PUT or POST request has submitted
malformed XML or JSON that the MessageBodyReader fails to parse. JAX-RS will also
throw this exception if it fails to convert a header or cookie value to the desired type.
For example:
@HeaderParam("Custom-Header") int header;
@CookieParam("myCookie") int cookie;
If the HTTP request’s Custom-Header value or the myCookie value cannot be parsed
into an integer, BadRequestException is thrown.
NotAuthorizedException is used when you want to write your own authentication
protocols. The 401 HTTP response code this exception represents requires you to send
back a challenge header called WWW-Authenticate. This header is used to tell the
client how it should authenticate with the server.
NotAuthorizedException has a few convenience constructors that make it easier to
build this header automatically:
For example, if we wanted to tell the client that OAuth Bearer tokens are required for
authentication, We would throw this exception:
Example:
@Path("/payer")
class CardPayer {
// We have Bank Account but we don't have credit card but we are trying to
// pay the money for online
// shopping throw online via with wrong credit cardNo
@GET
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/card/{card}")
public Response getCardDetails(@PathParam("card") String cardNo) {
PayerDao dao = new PayerDao();
boolean response = dao.pay(cardNo);
// Approach-2
if (response == false) {
throw new NotFoundException(Response.status(Status.NOT_FOUND)
.entity("<error>Entered Card Not Registered with us so plz apply for new
Card</error>")
.build());
}
String payement = "<payment>success</payment>";
return Response.ok(payement).build();
}
@PUT
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/online/{userName}/{password}")
public Response payAmountOnlineBanking(
@PathParam("userName") String userName,
@PathParam("password") String password) {
PayerDao dao = new PayerDao();
boolean response = dao.payOnline(userName, password);
// Approach-1
if (response == false) {
// InternalServerErrorException has predefined status-code as 500
throw new InternalServerErrorException();
}
// Approach-2
if (response == false) {
// ServiceUnavailableException has predefined status-code as 503
// throw new ServiceUnavailableException(); // (or)
throw new ServiceUnavailableException(
Response.status(Status.SERVICE_UNAVAILABLE)
.entity("<error>Currently this payment service is not available plz try after
24-Hours</error>").build());
}
// Approach-3
if (response == false) {
throw new ServiceUnavailableException("<error>Service is Unavailable
</error>",24L);
}
Approach: 3
http://localhost:8083/3.5SubExceptionClassesOfWebApplExceptionAndMappers/rest/
payer/online/dbreddy/dbreddy
Select PUT
Content-Type: text/plain
Response Status code-503 Service Unavailable (bcz we thrown
ServiceUnavailableException)
Response Headers
Retry-After: 24
8. JAX-RS exception hierarchy or Complete Exception Flow in JAX-RS API and
Overriding Error Details:
Our application code is allowed to throw any checked (classes extending
java.lang.Exception) or unchecked (classes extending java.lang.RuntimeException)
exceptions we want.
Thrown exceptions are handled by the JAX-RS runtime if we have registered an
exception mapper. Exception mappers can convert an exception to an HTTP response.
If the thrown exception is not handled by a mapper, it is propagated and handled by
the container (i.e., servlet) bcz JAX-RS is running within Web-Container/Servlet-
Container.
JAX-RS also provides the javax.ws.rs.WebApplicationException. This can be thrown by
application code and automatically processed by JAX-RS without having to write an
explicit mapper (If we want we can write mapper for WebApplicationException as well
and if we want we can send our error response by throwing WebApplicationException
with our error details so that it will not uses Default ExceptionMapper).
Our ExceptionMapper implementation must be annotated with the @Provider
annotation. This tells the JAX-RS runtime that it is a component. The class
implementing the ExceptionMapper interface must provide the parameterized type of
the ExceptionMapper. JAX-RS uses this generic type information to match up thrown
exceptions to ExceptionMappers. Finally, the toResponse() method receives the
thrown exception and creates a Response object that will be used to build the HTTP
response.
JAX-RS supports exception inheritance as well. When an exception is thrown, JAX-RS
will first try to find an ExceptionMapper for that exception’s type. If it cannot find one,
it will look for a mapper that can handle the exception’s superclass. It will continue
this process until there are no more super classes to match against.
Internal working Flow:
If we throw WebApplicationException with populated response then it will directly
prepares response and gives to the client. If we directly throw
WebApplicationException then it looks for is there any mapper for
WebApplicationException or not if founds then uses that mapper to prepare response
by calling toResponse() on that mapper.
@Provider
public class WebApplicationExceptionMapper implements
ExceptionMapper<WebApplicationException> {
}
@Provider
public class TransactionalExceptionMapper implements
ExceptionMapper<TransactionalException> {
}
@Provider
public class CardTransactionExceptionMapper implements
ExceptionMapper<CardTransactionException> {
}
@Path("/payer")
class CardPayer {
// We have Bank Account but we don't have credit card but we are trying to
// pay the money for online
// shopping throw online via with wrong credit cardNo
// Resource Method-1
// http://localhost:8083/3.6JAX-RSExceptionHeirarchy/rest/payer/card/C2
@PUT
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/card/{card}")
public Response payViaCard(@PathParam("card") String cardNo) {
PayerDao dao = new PayerDao();
boolean response = dao.pay(cardNo);
if (response == false) {
// Comment one to test it
// Case-1
// throw new CardTransactionException();
// Case-2
throw new CardTransactionException(Response.status(Status.NOT_FOUND)
.entity("<error>Entered Card in not registered with us for payment plz apply
for new Card</error>").build());
}
// Resource Method-2
@PUT
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/online/{userName}/{password}")
public Response payViaOnlineBanking(
@PathParam("userName") String userName,
@PathParam("password") String password) {
PayerDao dao = new PayerDao();
boolean response = dao.payOnline(userName, password);
if (response == false) {
throw new OnlineTransactionException();
}
String payement = "<payment>success</payment>";
return Response.ok(payement).build();
}
// Resource Method-3
// http://localhost:8083/3.6JAX-RSExceptionHeirarchy/rest/payer/wallet/W101
@PUT
@Consumes(MediaType.TEXT_PLAIN)
@Produces(MediaType.APPLICATION_XML)
@Path("/wallet/{walletNo}")
public Response paytmWallet(@PathParam("walletNo") String walletNo) {
PayerDao dao = new PayerDao();
boolean response = dao.walletPayment(walletNo);
if (response == false) {
throw new NotFoundException(Response.status(Status.NOT_FOUND)
.entity("<error>Invalid Wallet Id plz check walletId</error>")
.build());
}
String payement = "<payment>success</payment>";
return Response.ok(payement).build();
}
}
Access the application:
Resource Method-1:
Case: 1 (Comment case: 2 in programme)
http://localhost:8083/3.6JAX-
RSExceptionHeirarchyAndOverridingErrorDetails/rest/payer/card/C2
Select PUT
Content-Type: text/plain
Response:
Response Status code: 503 (Service Unavailable)
Response Body:
<error>(CardTransactionExceptionMapper) Try After 24-hours</error>
Case: 2 (Comment case: 1 in programme)
http://localhost:8083/3.6JAX-
RSExceptionHeirarchyAndOverridingErrorDetails/rest/payer/card/C2
Select PUT
Content-Type: text/plain
Response:
Response Status code: 404 (We given)
<error>Entered Card in not registered with us for payment plz apply for new
Card</error>
Resource Method-2:
http://localhost:8083/3.6JAX-RSExceptionHeirarchyAndOverridingErrorDetails
/rest/payer/online/dbreddy/dbreddy
Select PUT
Content-Type: text/plain
Status Code-503 (Service Unavailable)
Content-Type: text/plain
Response:
<error>Try After 24-hours</error>
Resource Method-3
http://localhost:8083/3.6JAX-
RSExceptionHeirarchyAndOverridingErrorDetails/rest/payer/wallet/W101
Select PUT
Content-Type: text/plain
Response:
Status Code-404 (NotFound)
Response Body:
<error>Invalid Wallet Id plz check walletId</error>
From this Resource Method-3 response we can observe that we can override error
details for any exception we want even though the mapper is available which is called
as "exception error details overriding".
JAX-RS Complete Exception Flow project Diagram:
How do you propagate the Exception or how do manage the Exceptions in case of
RESTful services?
Ans: When our Resource is encountering an Exception we just will not propagte that
exception back to the client rather we need to build our Response obj populating with
status codes to let the client to identify whether response getting as part of the body
is success or failure with an proper error message to communicate back easily. To
achieve this we are relaying on the Http Status codes bcz client can be anything
(java/.net) so that they can get this failure from the status codes in an interoperable
manner.
9. RESTful as DB-REST-Wrapper
|-Advantages of REST wrappers on top of the DB
|-Use Cases
RESTful as DB-REST-Wrapper:
For example 3-Appl wants to use data to access difficult to understand schema that's
where we can even use REST API there so that all the applications can read the data
from the REST Resource so that even though schema changes all the 3-appl no need
to worry bcz they are working with REST API so that no effect on the applications.
That means REST will used as wrappers on top of the DB's so that applications no
need to worry about schema and other things bcz REST taking care everything so if
we want any data or to insert the data we will talk to the REST only.
We may have a doubt if we wanted to talk to the REST we need to connect over the
network and in case of DB's also we need to connect to the network only bcz in real
application DB will be some other system so any how we are connecting to the DB to
perform the operations rather than connecting to the DB if we connect to the REST
that is there on top of the DB which is called as "DB-REST-Wrapper" so that it will
takes care of connecting to the DB and sends back the data back to the applications.
The REST and DB's both must will runs in the same system or intranet systems bcz
REST is wrapper on top of the DB, other we need to more appl which will connects
REST to DB which will kills the application performance. But if we connect to the REST
it will connects DB easily bcz both are in same system so that as like normal with 1-
network connection only we will get the data from the DB using REST hence there will
not be any performance issues as well.
Advantages of REST wrappers on top of the DB:
1. REST will abstract the schema model from the application point of view. so that any
no.of applications can communicate with same schema model if they have same type
of business applications for multiple applications or for per application bcz it free from
DB logic schema.
2. The cloud integrations means REST Wrappers only to connect with DB.
3. Every application or applications build REST to connect with DB bcz anyhow actual
application is going to communicate with DB over the network and tighly coupled to
the schema but if we go for REST-DB-Wrapper we will connect to the REST which will
in turn connects to the DB bcz both are running in same system so with same one
network connection itself we can get the data from DB and advantage is our
application free for changes in schema model of the DB and persistence related logic
of frame work logic.
Use Cases for REST Wrappers:
10. Wrapping Up:
In this chapter, we learned that JAX-RS has default response codes for both success
and error conditions. For more complex responses, your JAX-RS resource methods
can return javax.ws.rs.core.Response objects. JAX-RS has a few exception utilities.
We can throw instances of javax.ws.rs.WebApplicationException or let the underlying
servlet container handle the exception. Or, you can write an ExceptionMapper that
can map a particular exception to an HTTP response.