Skip to content

Commit 8286088

Browse files
author
Bhakti Mehta
committed
Sample showing how to map custom exceptions to HTTP Response codes
1 parent a27a43a commit 8286088

File tree

10 files changed

+375
-0
lines changed

10 files changed

+375
-0
lines changed

exception-mapper/Readme.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
This is a very basic sample which shows exception mapper and JAX-RS
2+
3+
Download Glassfish 4.0
4+
5+
Start Glassfish
6+
cd glassfish4/glassfish/bin
7+
./asadmin start-domain
8+
9+
Build the sample by running
10+
mvn clean install
11+
cd target
12+
deploy exception-mapper.war
13+
./asadmin deploy <folder of sample>/target/exception-mapper.war
14+
15+
16+
curl http://localhost:8080/exception-mapper/v1/coffees/orders/1/
17+
You will see response like this {"name":"Mocha","order":1,"size":"Small","type":"Brewed"}
18+
19+
curl http://localhost:8080/exception-mapper/v1/coffees/orders/100
20+
Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
21+
Server: GlassFish Server Open Source Edition 4.0
22+
Content-Type: application/json
23+
Date: Tue, 12 Aug 2014 00:08:18 GMT
24+
Content-Length: 54
25+
26+
{"code":404,"message":"No coffee found for order 100"}
27+
28+

exception-mapper/pom.xml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>exception-mapper</groupId>
8+
<artifactId>exception-mapper</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<packaging>war</packaging>
12+
<description>Basic "exception-mapper" sample</description>
13+
<dependencies>
14+
<dependency>
15+
<groupId>javax.ws.rs</groupId>
16+
<artifactId>javax.ws.rs-api</artifactId>
17+
<version>2.0-rc2</version>
18+
<scope>provided</scope>
19+
</dependency>
20+
21+
22+
<dependency>
23+
<groupId>javax</groupId>
24+
<artifactId>javaee-web-api</artifactId>
25+
<version>7.0</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
29+
<dependency>
30+
<groupId>javax.validation</groupId>
31+
<artifactId>validation-api</artifactId>
32+
<version>1.1.0.Beta2</version>
33+
<scope>provided</scope>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.glassfish.jersey.ext</groupId>
37+
<artifactId>jersey-bean-validation</artifactId>
38+
<version>2.1</version>
39+
<scope>provided</scope>
40+
</dependency>
41+
</dependencies>
42+
43+
<build>
44+
<plugins>
45+
<plugin>
46+
<groupId>org.apache.maven.plugins</groupId>
47+
<artifactId>maven-war-plugin</artifactId>
48+
<version>2.1-beta-1</version>
49+
<configuration>
50+
<failOnMissingWebXml>false</failOnMissingWebXml>
51+
</configuration>
52+
</plugin>
53+
54+
</plugins>
55+
<finalName>exception-mapper</finalName>
56+
</build>
57+
58+
</project>
59+
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.coffeeshop;
2+
3+
import javax.validation.constraints.NotNull;
4+
import javax.ws.rs.DefaultValue;
5+
import javax.xml.bind.annotation.XmlRootElement;
6+
import java.util.concurrent.atomic.AtomicInteger;
7+
8+
/**
9+
* A plain Coffee resource
10+
* @author Bhakti Mehta
11+
*/
12+
@XmlRootElement
13+
public class Coffee {
14+
15+
16+
private String type;
17+
18+
private String size;
19+
20+
@NotNull
21+
private String name;
22+
23+
private double price;
24+
25+
26+
private int order;
27+
28+
public Coffee(String type, String size,String name, double price) {
29+
this.type = type;
30+
this.size = size;
31+
this.name = name;
32+
this.price = price;
33+
this.order = getOrder();
34+
35+
}
36+
37+
public void setOrder(int order) {
38+
this.order = order;
39+
}
40+
41+
public int getOrder() {
42+
return CoffeeService.getCounter();
43+
}
44+
45+
46+
47+
public Coffee(){
48+
49+
}
50+
51+
public String getType() {
52+
return type;
53+
}
54+
55+
public void setType(String type) {
56+
this.type = type;
57+
}
58+
59+
public String getSize() {
60+
return size;
61+
}
62+
63+
public void setSize(String size) {
64+
this.size = size;
65+
}
66+
67+
public String getName() {
68+
return name;
69+
}
70+
71+
public void setName(String name) {
72+
this.name = name;
73+
}
74+
75+
public double getPrice() {
76+
return price;
77+
}
78+
79+
public void setPrice(double price) {
80+
this.price = price;
81+
}
82+
83+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.coffeeshop;
2+
3+
/**
4+
* This is an application which will register the JAX-RS resources
5+
* @author Bhakti Mehta
6+
*/
7+
8+
import org.glassfish.jersey.server.ServerProperties;
9+
import org.glassfish.jersey.server.validation.ValidationFeature;
10+
11+
import java.util.HashMap;
12+
import java.util.HashSet;
13+
import java.util.Map;
14+
import java.util.Set;
15+
16+
import javax.ws.rs.ApplicationPath;
17+
import javax.ws.rs.core.Application;
18+
19+
@ApplicationPath("/")
20+
public class CoffeeApplication extends Application {
21+
22+
@Override
23+
public Set<Class<?>> getClasses() {
24+
Set<Class<?>> classes = new HashSet<Class<?>>();
25+
classes.add(CoffeesResource.class);
26+
classes.add(MyExceptionMapper.class);
27+
return classes;
28+
}
29+
30+
31+
32+
33+
34+
}
35+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.coffeeshop;
2+
3+
/**
4+
* This is a custom exception thrown
5+
* in case the resource method does not find
6+
* any coffee orders
7+
* @author Bhakti Mehta
8+
*/
9+
public class CoffeeNotFoundException extends RuntimeException {
10+
11+
public CoffeeNotFoundException(String message) {
12+
super(message);
13+
}
14+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.coffeeshop;
2+
3+
import javax.ejb.Singleton;
4+
import java.util.HashMap;
5+
import java.util.concurrent.atomic.AtomicInteger;
6+
7+
/**
8+
* A basic collection of coffee orders for simplicity
9+
* @author Bhakti Mehta
10+
*/
11+
@Singleton
12+
public class CoffeeService {
13+
private static final HashMap<Integer, Coffee> coffees = new HashMap<Integer, Coffee>();
14+
private static AtomicInteger orderCounter = new AtomicInteger(0);
15+
16+
public static int incrementOrderCounter() {
17+
return orderCounter.incrementAndGet();
18+
}
19+
20+
21+
public static int addCoffee(Coffee coffee) {
22+
int counter = incrementOrderCounter();
23+
coffees.put(counter, coffee);
24+
return counter;
25+
}
26+
27+
public static int getSize() {
28+
return coffees.size();
29+
}
30+
31+
public static Coffee getCoffee(int order) {
32+
return coffees.get(order);
33+
}
34+
35+
public CoffeeService() {
36+
// initial content
37+
addCoffee(new Coffee("Brewed", "Small", "Mocha", 3.50));
38+
39+
}
40+
41+
public static int getCounter() {
42+
43+
return orderCounter.get();
44+
}
45+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.coffeeshop;
2+
3+
import org.glassfish.jersey.server.ChunkedOutput;
4+
5+
import javax.ws.rs.*;
6+
import javax.ws.rs.core.MediaType;
7+
import javax.ws.rs.core.Response;
8+
import javax.ws.rs.core.StreamingOutput;
9+
import java.io.*;
10+
11+
/**
12+
*
13+
* A simple JAX-RS resource which demonstrates custom exception handling
14+
* @author Bhakti Mehta
15+
*
16+
*/
17+
@Path("v1/coffees")
18+
public class CoffeesResource {
19+
20+
21+
@GET
22+
@Produces(MediaType.APPLICATION_JSON)
23+
@Path("/orders/{id}")
24+
public Response getCoffee(@PathParam("id") int id) {
25+
Coffee coffee = CoffeeService.getCoffee(id);
26+
if (coffee == null)
27+
throw new CoffeeNotFoundException("No coffee found for order " + id);
28+
return Response.ok(coffee).type(MediaType.APPLICATION_JSON_TYPE).build();
29+
}
30+
31+
32+
33+
34+
35+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.coffeeshop;
2+
3+
import javax.ws.rs.core.MediaType;
4+
import javax.ws.rs.core.Response;
5+
import javax.ws.rs.ext.ExceptionMapper;
6+
import javax.ws.rs.ext.Provider;
7+
8+
/**
9+
* This is an implementation of the ExceptionMapper class
10+
* to convert a user defined Exception to a JAX-RS response
11+
* @author Bhakti Mehta
12+
*/
13+
@Provider
14+
public class MyExceptionMapper implements ExceptionMapper<Exception> {
15+
16+
public Response toResponse(Exception e) {
17+
ResourceError resourceError = new ResourceError();
18+
19+
String error = "Service encountered an internal error";
20+
if (e instanceof CoffeeNotFoundException) {
21+
resourceError.setCode(Response.Status.NOT_FOUND.getStatusCode());
22+
resourceError.setMessage(e.getMessage());
23+
24+
return Response.status(Response.Status.NOT_FOUND).entity(resourceError)
25+
.type(MediaType.APPLICATION_JSON_TYPE)
26+
.build();
27+
}
28+
return Response.status(503).entity(resourceError).type(MediaType.APPLICATION_JSON_TYPE)
29+
.build();
30+
}
31+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.coffeeshop;
2+
3+
/**
4+
* A basic class to indicate preference for coffee
5+
* @author Bhakti Mehta
6+
*/
7+
public enum Preference {
8+
NonFat, Regular, Lowfat;
9+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.coffeeshop;
2+
3+
import javax.xml.bind.annotation.XmlRootElement;
4+
5+
/**
6+
* This is a user defined class which will contain
7+
* the status code and response message when an error occurs
8+
* @author Bhakti Mehta
9+
*/
10+
@XmlRootElement
11+
public class ResourceError {
12+
13+
private int code;
14+
15+
private String message;
16+
17+
public int getCode() {
18+
return code;
19+
}
20+
21+
public void setCode(int code) {
22+
this.code = code;
23+
}
24+
25+
public String getMessage() {
26+
return message;
27+
}
28+
29+
public void setMessage(String message) {
30+
this.message = message;
31+
}
32+
33+
public ResourceError(){
34+
35+
}
36+
}

0 commit comments

Comments
 (0)