Implemented OAuth2 exception handler.

Change-Id: I5363e42ee78fa74de982cda3215247c7e73137bb
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/OAuth2ClientDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/OAuth2ClientDao.java
index 8d678b8..b8546ae 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/OAuth2ClientDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/OAuth2ClientDao.java
@@ -49,10 +49,10 @@
     }
 
     public OAuth2Client retrieveClientById (String clientId)
-            throws Exception {
+            throws KustvaktException {
 
         ParameterChecker.checkStringValue(clientId, "client_id");
-        
+
         CriteriaBuilder builder = entityManager.getCriteriaBuilder();
         CriteriaQuery<OAuth2Client> query =
                 builder.createQuery(OAuth2Client.class);
@@ -62,13 +62,13 @@
         query.where(builder.equal(root.get(OAuth2Client_.id), clientId));
 
         Query q = entityManager.createQuery(query);
-//        try {
+        try {
             return (OAuth2Client) q.getSingleResult();
-//        }
-//        catch (NoResultException e) {
-//            throw new KustvaktException(StatusCodes.CLIENT_NOT_FOUND,
-//                    "Client with id " + clientId + " is not found");
-//        }
+        }
+        catch (Exception e) {
+            throw new KustvaktException(StatusCodes.CLIENT_NOT_FOUND,
+                    e.getMessage(), "invalid_client");
+        }
     }
 
     public void deregisterClient (OAuth2Client client) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java b/full/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java
index 83e4d9e..a2acc05 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/AnnotationService.java
@@ -15,7 +15,6 @@
 import de.ids_mannheim.korap.entity.AnnotationPair;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.web.CoreResponseHandler;
 import de.ids_mannheim.korap.web.controller.AnnotationController;
 
 /** AnnotationService defines the logic behind {@link AnnotationController}.
@@ -30,9 +29,6 @@
             LoggerFactory.getLogger(AnnotationService.class);
 
     @Autowired
-    CoreResponseHandler kustvaktResponseHandler;
-
-    @Autowired
     private AnnotationDao annotationDao;
 
     @Autowired
@@ -68,9 +64,8 @@
                 }
                 else {
                     jlog.error("Annotation code is wrong: " + annotationCode);
-                    kustvaktResponseHandler.throwit(
-                            new KustvaktException(StatusCodes.INVALID_ATTRIBUTE,
-                                    "Bad attribute:", code));
+                    throw new KustvaktException(StatusCodes.INVALID_ATTRIBUTE,
+                            "Bad attribute:", code);
                 }
 
                 annotationPairs.addAll(annotationDao
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/OAuth2ClientService.java b/full/src/main/java/de/ids_mannheim/korap/service/OAuth2ClientService.java
index 3a44e51..0109ea8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/OAuth2ClientService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/OAuth2ClientService.java
@@ -2,8 +2,6 @@
 
 import java.sql.SQLException;
 
-import javax.servlet.http.HttpServletResponse;
-
 import org.apache.commons.validator.routines.UrlValidator;
 import org.apache.oltu.oauth2.common.error.OAuthError;
 import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
@@ -62,13 +60,14 @@
             String registeredBy) throws KustvaktException {
         if (!urlValidator.isValid(clientJson.getUrl())) {
             throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
-                    clientJson.getUrl() + " is invalid.", clientJson.getUrl());
+                    clientJson.getUrl() + " is invalid.",
+                    OAuthError.TokenResponse.INVALID_REQUEST);
         }
         if (!httpsValidator.isValid(clientJson.getRedirectURI())) {
             throw new KustvaktException(StatusCodes.HTTPS_REQUIRED,
                     clientJson.getRedirectURI()
                             + " is invalid. RedirectURI requires https.",
-                    clientJson.getRedirectURI());
+                    OAuthError.TokenResponse.INVALID_REQUEST);
         }
 
         String secret = null;
@@ -104,7 +103,8 @@
                 if (cause instanceof SQLException) {
                     throw new KustvaktException(
                             StatusCodes.CLIENT_REGISTRATION_FAILED,
-                            cause.getMessage(), cause);
+                            cause.getMessage(),
+                            OAuthError.TokenResponse.INVALID_REQUEST);
                 }
                 lastCause = cause;
             }
@@ -115,7 +115,7 @@
 
 
     public void deregisterPublicClient (String clientId, String username)
-            throws KustvaktException, OAuthProblemException {
+            throws KustvaktException {
 
         OAuth2Client client = retrieveClientById(clientId);
         if (adminDao.isAdmin(username)) {
@@ -126,7 +126,8 @@
                     StatusCodes.CLIENT_DEREGISTRATION_FAILED,
                     "Service is limited to public clients. To deregister "
                             + "confidential clients, use service at path: "
-                            + "oauth2/client/deregister/confidential.");
+                            + "oauth2/client/deregister/confidential.",
+                    OAuthError.TokenResponse.INVALID_REQUEST);
         }
         else if (client.getRegisteredBy().equals(username)) {
             clientDao.deregisterClient(client);
@@ -139,19 +140,19 @@
 
 
     public void deregisterConfidentialClient (String authorization,
-            String clientId) throws KustvaktException, OAuthProblemException {
+            String clientId) throws KustvaktException {
         OAuth2Client client =
                 authenticateClientByBasicAuthorization(authorization, clientId);
         clientDao.deregisterClient(client);
     }
 
     public OAuth2Client authenticateClientById (String clientId)
-            throws OAuthProblemException {
+            throws KustvaktException {
         if (clientId == null || clientId.isEmpty()) {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.INVALID_REQUEST)
-                    .description("client_id is missing.")
-                    .responseStatus(HttpServletResponse.SC_BAD_REQUEST);
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                    "client_id is missing.",
+                    OAuthError.TokenResponse.INVALID_CLIENT);
         }
         else {
             return retrieveClientById(clientId);
@@ -159,14 +160,13 @@
     }
 
     public OAuth2Client authenticateClientByBasicAuthorization (
-            String authorization, String clientId)
-            throws KustvaktException, OAuthProblemException {
+            String authorization, String clientId) throws KustvaktException {
 
         if (authorization == null || authorization.isEmpty()) {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.INVALID_REQUEST)
-                    .description("Authorization header is not found.")
-                    .responseStatus(HttpServletResponse.SC_BAD_REQUEST);
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                    "Authorization header is not found.",
+                    OAuthError.TokenResponse.INVALID_CLIENT);
         }
         else {
             AuthorizationData authData = authorizationHandler
@@ -177,61 +177,41 @@
                 return verifyClientCredentials(clientId, authData);
             }
             else {
-                throw OAuthProblemException
-                        .error(OAuthError.TokenResponse.INVALID_CLIENT)
-                        .description(
-                                "Client authentication with "
-                                        + authData.getAuthenticationScheme()
-                                                .displayName()
-                                        + "is not supported")
-                        .responseStatus(HttpServletResponse.SC_BAD_REQUEST);
+                throw new KustvaktException(
+                        StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                        "Client authentication with " + authData
+                                .getAuthenticationScheme().displayName()
+                                + "is not supported",
+                        "invalid_client");
             }
         }
     }
 
     private OAuth2Client verifyClientCredentials (String clientId,
-            AuthorizationData authData) throws OAuthProblemException {
+            AuthorizationData authData) throws KustvaktException {
 
-        try {
-            OAuth2Client client = retrieveClientById(authData.getUsername());
-            // EM: not sure if this is necessary
-            if (clientId != null && !clientId.isEmpty()) {
-                if (!client.getId().equals(clientId)) {
-                    throw new KustvaktException(
-                            StatusCodes.CLIENT_AUTHENTICATION_FAILED);
-                }
-            }
-            if (!encryption.checkHash(authData.getPassword(),
-                    client.getSecret(), config.getPasscodeSaltField())) {
+        OAuth2Client client = retrieveClientById(authData.getUsername());
+        // EM: not sure if this is necessary
+        if (clientId != null && !clientId.isEmpty()) {
+            if (!client.getId().equals(clientId)) {
                 throw new KustvaktException(
-                        StatusCodes.CLIENT_AUTHENTICATION_FAILED);
+                        StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                        "Invalid client credentials.",
+                        OAuthError.TokenResponse.INVALID_CLIENT);
             }
-            return client;
         }
-        catch (Exception e) {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.INVALID_CLIENT)
-                    .description("Invalid client credentials.")
-                    .responseStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        if (!encryption.checkHash(authData.getPassword(), client.getSecret(),
+                config.getPasscodeSaltField())) {
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                    "Invalid client credentials.",
+                    OAuthError.TokenResponse.INVALID_CLIENT);
         }
+        return client;
     }
 
     public OAuth2Client retrieveClientById (String clientId)
-            throws OAuthProblemException {
-        try {
-            return clientDao.retrieveClientById(clientId);
-        }
-        catch (KustvaktException e) {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.INVALID_REQUEST)
-                    .description(e.getMessage() + "is missing.")
-                    .responseStatus(HttpServletResponse.SC_BAD_REQUEST);
-        }
-        catch (Exception e) {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.INVALID_CLIENT)
-                    .description("Invalid client credentials.")
-                    .responseStatus(HttpServletResponse.SC_UNAUTHORIZED);
-        }
+            throws KustvaktException {
+        return clientDao.retrieveClientById(clientId);
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/OAuth2Service.java b/full/src/main/java/de/ids_mannheim/korap/service/OAuth2Service.java
index b69b248..9338bfe 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/OAuth2Service.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/OAuth2Service.java
@@ -21,6 +21,7 @@
 import de.ids_mannheim.korap.constant.OAuth2ClientType;
 import de.ids_mannheim.korap.entity.OAuth2Client;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 
 @Service
 public class OAuth2Service {
@@ -52,29 +53,26 @@
      * @throws OAuthSystemException 
      */
     public OAuthResponse requestAccessToken (HttpServletRequest request,
-            String authorization, GrantType grantType, String authorizationCode,
+            String authorization, String grantType, String authorizationCode,
             String redirectURI, String clientId, String username,
-            String password, String scope)
-            throws KustvaktException, OAuthProblemException {
+            String password, String scope) throws KustvaktException {
 
-        if (grantType.equals(GrantType.AUTHORIZATION_CODE)) {
+        if (grantType.equals(GrantType.AUTHORIZATION_CODE.toString())) {
             return requestAccessTokenWithAuthorizationCode(authorization,
                     authorizationCode, redirectURI, clientId);
         }
-        else if (grantType.equals(GrantType.PASSWORD)) {
+        else if (grantType.equals(GrantType.PASSWORD.toString())) {
             return requestAccessTokenWithPassword(authorization, username,
                     password, scope);
         }
-        else if (grantType.equals(GrantType.CLIENT_CREDENTIALS)) {
+        else if (grantType.equals(GrantType.CLIENT_CREDENTIALS.toString())) {
             return requestAccessTokenWithClientCredentials(authorization,
                     scope);
         }
         else {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE)
-                    .description(grantType.name() + "is not supported.")
-                    .responseStatus(HttpServletResponse.SC_BAD_REQUEST);
-
+            throw new KustvaktException(StatusCodes.UNSUPPORTED_GRANT_TYPE,
+                    grantType + " is not supported.",
+                    OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE);
         }
 
     }
@@ -92,16 +90,15 @@
      */
     private OAuthResponse requestAccessTokenWithAuthorizationCode (
             String authorization, String authorizationCode, String redirectURI,
-            String clientId) throws KustvaktException, OAuthProblemException {
+            String clientId) throws KustvaktException {
         OAuth2Client client;
         if (authorization == null || authorization.isEmpty()) {
             client = clientService.authenticateClientById(clientId);
             if (client.getType().equals(OAuth2ClientType.CONFIDENTIAL)) {
-                throw OAuthProblemException
-                        .error(OAuthError.TokenResponse.INVALID_CLIENT)
-                        .description("Client authentication using "
-                                + "authorization header is required.")
-                        .responseStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                throw new KustvaktException(
+                        StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                        "Client authentication using authorization header is required.",
+                        OAuthError.TokenResponse.INVALID_CLIENT);
             }
         }
         else {
@@ -138,15 +135,13 @@
      * @throws KustvaktException 
      */
     private OAuthResponse requestAccessTokenWithClientCredentials (
-            String authorization, String scope)
-            throws OAuthProblemException, KustvaktException {
+            String authorization, String scope) throws KustvaktException {
 
         if (authorization == null || authorization.isEmpty()) {
-            throw OAuthProblemException
-                    .error(OAuthError.TokenResponse.INVALID_CLIENT)
-                    .description("Client authentication using "
-                            + "authorization header is required.")
-                    .responseStatus(HttpServletResponse.SC_UNAUTHORIZED);
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                    "Client authentication using authorization header is required.",
+                    OAuthError.TokenResponse.INVALID_CLIENT);
         }
         else {
             OAuth2Client client =
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/FullResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/KustvaktExceptionHandler.java
similarity index 95%
rename from full/src/main/java/de/ids_mannheim/korap/web/FullResponseHandler.java
rename to full/src/main/java/de/ids_mannheim/korap/web/KustvaktExceptionHandler.java
index d836ead..e17cd0a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/FullResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/KustvaktExceptionHandler.java
@@ -18,12 +18,12 @@
  * @author margaretha
  *
  */
-public class FullResponseHandler extends CoreResponseHandler {
+public class KustvaktExceptionHandler extends CoreResponseHandler {
 
     @Autowired
     private HttpUnauthorizedHandler handler;
 
-    public FullResponseHandler (AuditingIface iface) {
+    public KustvaktExceptionHandler (AuditingIface iface) {
         super(iface);
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ExceptionHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ExceptionHandler.java
new file mode 100644
index 0000000..3d849af
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ExceptionHandler.java
@@ -0,0 +1,126 @@
+package de.ids_mannheim.korap.web;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.oltu.oauth2.common.error.OAuthError;
+import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
+import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.apache.oltu.oauth2.common.message.OAuthResponse;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.interfaces.db.AuditingIface;
+
+/** OAuth2ExceptionHandler maps {@link KustvaktException} to 
+ * {@link OAuthProblemException} and creates {@link Response} 
+ * accordingly. 
+ * 
+ * <br/><br/>
+ * 
+ * OAuth2 error response consists of error (required), 
+ * error_description (optional) and error_uri (optional).
+ * 
+ * According to RFC 6749, error indicates error code 
+ * categorized into:
+ * <ul>
+ * <li>invalid_request: The request is missing a required parameter, 
+ * includes an unsupported parameter value (other than grant type),
+ * repeats a parameter, includes multiple credentials, utilizes 
+ * more than one mechanism for authenticating the client, or is 
+ * otherwise malformed.</li>
+ * 
+ * <li>invalid_client: Client authentication failed (e.g., unknown 
+ * client, no client authentication included, or unsupported 
+ * authentication method).  The authorization sever MAY return 
+ * an HTTP 401 (Unauthorized) status code to indicate which 
+ * HTTP authentication schemes are supported. If the client 
+ * attempted to authenticate via the "Authorization" request 
+ * header field, the authorization server MUST respond with 
+ * an HTTP 401 (Unauthorized) status code and include 
+ * the "WWW-Authenticate" response header field matching 
+ * the authentication scheme used by the client</li>
+ * 
+ * <li>invalid_grant: The provided authorization grant 
+ * (e.g., authorization code, resource owner credentials) or 
+ * refresh token is invalid, expired, revoked, does not match 
+ * the redirection URI used in the authorization request, or 
+ * was issued to another client.</li>
+ * 
+ * <li>unauthorized_client:The authenticated client is not 
+ * authorized to use this authorization grant type.</li>
+ * 
+ * <li>unsupported_grant_type: The authorization grant type 
+ * is not supported by the authorization server.</li>
+ * 
+ * <li>invalid_scope: The requested scope is invalid, unknown, 
+ * malformed, or exceeds the scope granted by the resource owner.</li>
+ * </ul>
+ * 
+ * 
+ * @author margaretha
+ *
+ */
+public class OAuth2ExceptionHandler extends CoreResponseHandler {
+
+    public OAuth2ExceptionHandler (AuditingIface iface) {
+        super(iface);
+    }
+
+    @Override
+    public WebApplicationException throwit (KustvaktException e) {
+        OAuthResponse oAuthResponse = null;
+        String errorCode = e.getEntity();
+        try {
+            if (errorCode.equals(OAuthError.TokenResponse.INVALID_CLIENT)) {
+                oAuthResponse = createOAuthResponse(e,
+                        Status.UNAUTHORIZED.getStatusCode());
+            }
+            else if (errorCode.equals(OAuthError.TokenResponse.INVALID_GRANT)
+                    || errorCode
+                            .equals(OAuthError.TokenResponse.INVALID_REQUEST)
+                    || errorCode.equals(OAuthError.TokenResponse.INVALID_SCOPE)
+                    || errorCode
+                            .equals(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)
+                    || errorCode.equals(
+                            OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE)) {
+                oAuthResponse = createOAuthResponse(e,
+                        Status.BAD_REQUEST.getStatusCode());
+
+            }
+            else {
+                return super.throwit(e);
+            }
+        }
+        catch (OAuthSystemException e1) {
+            Response r = Response.status(Status.BAD_REQUEST)
+                    .entity(e1.getMessage()).build();
+            return new WebApplicationException(r);
+        }
+
+        Response r = createResponse(oAuthResponse);
+        return new WebApplicationException(r);
+    }
+
+    private OAuthResponse createOAuthResponse (KustvaktException e,
+            int statusCode) throws OAuthSystemException {
+        OAuthProblemException oAuthProblemException = OAuthProblemException
+                .error(e.getEntity()).description(e.getMessage());
+        return OAuthResponse.errorResponse(statusCode)
+                .error(oAuthProblemException).buildJSONMessage();
+    }
+
+    private Response createResponse (OAuthResponse oAuthResponse) {
+        ResponseBuilder builder =
+                Response.status(oAuthResponse.getResponseStatus());
+        builder.entity(oAuthResponse.getBody());
+        if (oAuthResponse.getResponseStatus() == Status.UNAUTHORIZED
+                .getStatusCode()) {
+            builder.header(HttpHeaders.WWW_AUTHENTICATE,
+                    "Basic realm=\"Kustvakt\"");
+        }
+        return builder.build();
+    }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/AdminController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/AdminController.java
index f85016a..9bb3ac8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/AdminController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/AdminController.java
@@ -26,7 +26,7 @@
 import de.ids_mannheim.korap.server.KustvaktServer;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
-import de.ids_mannheim.korap.web.CoreResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 import de.ids_mannheim.korap.web.filter.AdminFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 
@@ -49,7 +49,7 @@
     private AuditingIface auditingController;
 
     @Autowired
-    CoreResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktExceptionHandler;
 
     // EM: not documented and tested, not sure what the purpose of the service is
     @GET
@@ -75,7 +75,7 @@
             integer_limit = Integer.valueOf(limit);
         }
         catch (NumberFormatException | NullPointerException e) {
-            throw kustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
+            throw kustvaktExceptionHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT);
         }
         String result="";
         try {
@@ -84,7 +84,7 @@
                     until_date, dayOnly, integer_limit));
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         // limit number of records to return
         return Response.ok(result).build();
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java
index 09cebff..68ffb47 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/AnnotationController.java
@@ -22,7 +22,7 @@
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.service.AnnotationService;
 import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.web.CoreResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 
@@ -39,7 +39,7 @@
 public class AnnotationController {
 
     @Autowired
-    CoreResponseHandler responseHandler;
+    private KustvaktExceptionHandler responseHandler;
 
     @Autowired
     private AnnotationService annotationService;
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
index 1e783c2..e075321 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
@@ -44,7 +44,7 @@
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.KustvaktLogger;
 import de.ids_mannheim.korap.utils.ServiceInfo;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
@@ -63,7 +63,7 @@
 public class AuthenticationController {
 
     @Autowired
-    private FullResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktExceptionHandler;
     
     @Autowired
     private HttpAuthorizationHandler authorizationHandler;
@@ -102,7 +102,7 @@
             return Response.ok(JsonUtils.toJSON(m)).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -121,7 +121,7 @@
             return Response.ok(ctx.toJson()).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
     
@@ -158,7 +158,7 @@
             return Response.ok(context.toJson()).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -178,7 +178,7 @@
         List<String> auth =
                 headers.getRequestHeader(ContainerRequest.AUTHORIZATION);
         if (auth == null || auth.isEmpty()) {
-            throw kustvaktResponseHandler
+            throw kustvaktExceptionHandler
                     .throwit(new KustvaktException(StatusCodes.MISSING_ARGUMENT,
                             "Authorization header is missing.",
                             "Authorization header"));
@@ -197,7 +197,7 @@
            
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         if (DEBUG_LOG == true) {
@@ -240,7 +240,7 @@
                 authorizationData.getPassword()== null || 
                 authorizationData.getPassword().isEmpty())
             // is actual an invalid request
-            throw kustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
+            throw kustvaktExceptionHandler.throwit(StatusCodes.REQUEST_INVALID);
 
         Map<String, Object> attr = new HashMap<>();
         if (scopes != null && !scopes.isEmpty())
@@ -268,14 +268,14 @@
 //                    Attributes.API_AUTHENTICATION);
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         try {
             return Response.ok(context.toJson()).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -318,7 +318,7 @@
            
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         // Implementation Hanl mit '|'. 16.02.17/FB
@@ -329,7 +329,7 @@
                 authorizationData.getPassword()== null || 
                 authorizationData.getPassword().isEmpty())
             // is actual an invalid request
-            throw kustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
+            throw kustvaktExceptionHandler.throwit(StatusCodes.REQUEST_INVALID);
 
         Map<String, Object> attr = new HashMap<>();
         attr.put(Attributes.HOST, host);
@@ -348,7 +348,7 @@
             jlog.debug(contextJson);
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().entity(contextJson).build();
     }
@@ -382,13 +382,13 @@
             context = controller.createTokenContext(user, attr, null);
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         try {
             return Response.ok().entity(context.toJson()).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -406,7 +406,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Logout Exception: {}", e.string());
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().build();
     }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/DocumentController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/DocumentController.java
index f1adb38..aafb569 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/DocumentController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/DocumentController.java
@@ -1,25 +1,30 @@
 package de.ids_mannheim.korap.web.controller;
 
-import com.sun.jersey.spi.container.ResourceFilters;
-import de.ids_mannheim.korap.config.BeansFactory;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.handlers.DocumentDao;
-import de.ids_mannheim.korap.resources.Document;
-import de.ids_mannheim.korap.server.KustvaktServer;
-import de.ids_mannheim.korap.utils.JsonUtils;
-import de.ids_mannheim.korap.utils.KustvaktLogger;
-import de.ids_mannheim.korap.web.CoreResponseHandler;
-import de.ids_mannheim.korap.web.filter.AdminFilter;
+import java.util.List;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import javax.ws.rs.*;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.util.List;
+import com.sun.jersey.spi.container.ResourceFilters;
+
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.DocumentDao;
+import de.ids_mannheim.korap.resources.Document;
+import de.ids_mannheim.korap.server.KustvaktServer;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
+import de.ids_mannheim.korap.web.filter.AdminFilter;
 
 /**
  * EM: To Do: restructure codes regarding service and controller layers
@@ -35,8 +40,8 @@
 public class DocumentController {
 
     @Autowired
-    CoreResponseHandler kustvaktResponseHandler;
-    
+    private KustvaktExceptionHandler kustvaktExceptionHandler;
+
     private static Logger jlog =
             LoggerFactory.getLogger(DocumentController.class);
     private DocumentDao documentDao;
@@ -52,7 +57,7 @@
             this.documentDao.storeResource(doc, null);
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -73,7 +78,7 @@
             return Response.ok(JsonUtils.toJSON(docs)).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java
index 32663f5..1a1ef0e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/KustvaktController.java
@@ -26,7 +26,7 @@
 
     private static Logger jlog = LoggerFactory.getLogger(UserController.class);
     @Autowired
-    private CoreResponseHandler kustvaktResponseHandler;
+    private CoreResponseHandler kustvaktExceptionHandler;
 
 
     @Path("info")
@@ -39,7 +39,7 @@
             return Response.ok(JsonUtils.toJSON(m)).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
index 08d2a0a..d3163e6 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
@@ -14,23 +14,20 @@
 import javax.ws.rs.core.SecurityContext;
 
 import org.apache.http.HttpHeaders;
-import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
 import org.apache.oltu.oauth2.common.message.OAuthResponse;
-import org.apache.oltu.oauth2.common.message.types.GrantType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.service.OAuth2Service;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.OAuth2ExceptionHandler;
 
 @Controller
 @Path("/oauth2")
 public class OAuth2Controller {
 
     @Autowired
-    private FullResponseHandler responseHandler;
+    private OAuth2ExceptionHandler responseHandler;
     @Autowired
     private OAuth2Service oauth2Service;
 
@@ -59,7 +56,7 @@
             @Context SecurityContext securityContext,
             @HeaderParam("Authorization") String authorization,
             // required for all grants
-            @FormParam("grant_type") GrantType grantType,
+            @FormParam("grant_type") String grantType,
             // required for Authorization Code Grant
             @FormParam("code") String authorizationCode,
             @FormParam("redirect_uri") String redirectURI,
@@ -85,8 +82,5 @@
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java
index d7eb33e..fa406ac 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java
@@ -12,7 +12,6 @@
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 
-import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -22,7 +21,8 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.service.OAuth2ClientService;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
+import de.ids_mannheim.korap.web.OAuth2ExceptionHandler;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
@@ -41,7 +41,7 @@
     @Autowired
     private OAuth2ClientService clientService;
     @Autowired
-    private FullResponseHandler responseHandler;
+    private OAuth2ExceptionHandler responseHandler;
 
     /** Registers a client application. Before starting an OAuth process, 
      * client applications have to be registered first. Only registered
@@ -104,9 +104,6 @@
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
     }
 
 
@@ -124,8 +121,5 @@
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthController.java
index 3a91014..e457cea 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthController.java
@@ -74,7 +74,7 @@
 public class OAuthController {
 
     @Autowired
-    CoreResponseHandler kustvaktResponseHandler;
+    CoreResponseHandler kustvaktExceptionHandler;
     
     private OAuth2Handler handler;
     @Autowired
@@ -159,7 +159,7 @@
             json = JsonUtils.toJSON(Scopes.mapScopes(scopes, data));
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         // json format with scope callback parameter
         // todo: add other scopes as well!
@@ -184,7 +184,7 @@
             return Response.ok(JsonUtils.toJSON(auths)).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -232,7 +232,7 @@
 //                user.addUserData(data);
             }
             catch (KustvaktException e) {
-                throw kustvaktResponseHandler.throwit(e);
+                throw kustvaktExceptionHandler.throwit(e);
             }
 
             // register response according to response_type
@@ -308,7 +308,7 @@
                     this.handler.authorize(codeInfo, user);
                 }
                 catch (KustvaktException e) {
-                    throw kustvaktResponseHandler.throwit(e);
+                    throw kustvaktExceptionHandler.throwit(e);
                 }
                 builder.setParam(OAuth.OAUTH_RESPONSE_TYPE,
                         ResponseType.CODE.toString());
@@ -344,7 +344,7 @@
                                 new_context.getToken());
                     }
                     catch (KustvaktException e) {
-                        throw kustvaktResponseHandler.throwit(e);
+                        throw kustvaktExceptionHandler.throwit(e);
                     }
                 }
                 response = builder.buildBodyMessage();
@@ -529,7 +529,7 @@
                     }
                 }
                 catch (KustvaktException e) {
-                    throw kustvaktResponseHandler.throwit(e);
+                    throw kustvaktExceptionHandler.throwit(e);
                 }
                 // todo: errors for invalid scopes or different scopes then during authorization request?
                 //todo ??
@@ -559,7 +559,7 @@
                             oauthRequest.getPassword(), attr);
                 }
                 catch (KustvaktException e) {
-                    throw kustvaktResponseHandler.throwit(e);
+                    throw kustvaktExceptionHandler.throwit(e);
                 }
 
                 try {
@@ -581,7 +581,7 @@
 
                 }
                 catch (KustvaktException e) {
-                    throw kustvaktResponseHandler.throwit(e);
+                    throw kustvaktExceptionHandler.throwit(e);
                 }
             }
 
@@ -606,7 +606,7 @@
                     builder.setParam(c.getTokenType().displayName(), c.getToken());
                 }
                 catch (KustvaktException e) {
-                    throw kustvaktResponseHandler.throwit(e);
+                    throw kustvaktExceptionHandler.throwit(e);
                 }
             }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
index d97052b..e64bcfe 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
@@ -82,7 +82,7 @@
             LoggerFactory.getLogger(SearchController.class);
 
     @Autowired
-    private CoreResponseHandler responseHandler;
+    private CoreResponseHandler kustvaktExceptionHandler;
     @Autowired
     private SearchKrill searchKrill;
     private ResourceCache resourceHandler;
@@ -215,7 +215,7 @@
             result = graphDBhandler.getResponse("distCollo", "q", query);
         }
         catch (KustvaktException e) {
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok(result).build();
     }
@@ -323,7 +323,7 @@
             cquery.setBaseQuery(ss.toJSON());
         }
         catch (KustvaktException e1) {
-            throw responseHandler.throwit(e1);
+            throw kustvaktExceptionHandler.throwit(e1);
         }
 
         String query = "";
@@ -343,7 +343,7 @@
                 }
             }
             catch (KustvaktException e) {
-                throw responseHandler.throwit(e);
+                throw kustvaktExceptionHandler.throwit(e);
             }
         }
 
@@ -399,7 +399,7 @@
             // jsonld = this.processor.processQuery(jsonld, user);
         }
         catch (KustvaktException e) {
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         jlog.info("Serialized search: {}", jsonld);
 
@@ -434,7 +434,7 @@
         catch (KustvaktException e) {
             jlog.error("Failed retrieving user in the search service: {}",
                     e.string());
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         QuerySerializer serializer = new QuerySerializer();
@@ -451,7 +451,7 @@
             jlog.info("the serialized query {}", query);
         }
         catch (KustvaktException e) {
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         String result = doSearch(eng, query, pageLength, meta);
@@ -496,7 +496,7 @@
             MetaQueryBuilder meta, boolean raw) {
 
         if (raw) {
-            throw responseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+            throw kustvaktExceptionHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
                     "raw not supported!", null);
         }
 
@@ -510,7 +510,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Failed searching in Neo4J: {}", e.string());
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
     }
@@ -535,7 +535,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered: {}", e.string());
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         VirtualCollection tmp = resourceHandler.getCache(cache.getId(),
@@ -548,7 +548,7 @@
                 cache.setStats(JsonUtils.convertToClass(stats, Map.class));
             }
             catch (KustvaktException e) {
-                throw responseHandler.throwit(e);
+                throw kustvaktExceptionHandler.throwit(e);
             }
             resourceHandler.cache(cache);
         }
@@ -562,7 +562,7 @@
             return Response.ok(JsonUtils.toJSON(vals)).build();
         }
         catch (KustvaktException e) {
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -599,7 +599,7 @@
         catch (KustvaktException e) {
             jlog.error("Failed getting user in the matchInfo service: {}",
                     e.string());
-            throw responseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         CorpusAccess corpusAccess = user.getCorpusAccess();
@@ -642,7 +642,7 @@
         }
         catch (Exception e) {
             jlog.error("Exception in the MatchInfo service encountered!", e);
-            throw responseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+            throw kustvaktExceptionHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
                     e.getMessage(), "");
         }
         jlog.debug("MatchInfo results: " + results);
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
index be74ec8..a468302 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/StatisticController.java
@@ -44,7 +44,7 @@
     private static Logger jlog =
             LoggerFactory.getLogger(StatisticController.class);
     @Autowired
-    private CoreResponseHandler kustvaktResponseHandler;
+    private CoreResponseHandler kustvaktExceptionHandler;
     @Autowired
     private SearchKrill searchKrill;
 
@@ -68,7 +68,7 @@
             @QueryParam("corpusQuery") String corpusQuery) {
 
         if (corpusQuery == null || corpusQuery.isEmpty()) {
-            throw kustvaktResponseHandler
+            throw kustvaktExceptionHandler
                     .throwit(new KustvaktException(StatusCodes.MISSING_ARGUMENT,
                             "Parameter corpusQuery is missing.",
                             "corpusQuery"));
@@ -82,12 +82,12 @@
             json = builder.toJSON();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         String stats = searchKrill.getStatistics(json);
         if (stats.contains("-1"))
-            throw kustvaktResponseHandler.throwit(StatusCodes.NO_RESULT_FOUND);
+            throw kustvaktExceptionHandler.throwit(StatusCodes.NO_RESULT_FOUND);
         jlog.debug("Stats: " + stats);
         return Response.ok(stats).build();
     }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java
index 670840b..2cda085 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java
@@ -52,7 +52,7 @@
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.StringUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
@@ -71,7 +71,7 @@
 public class UserController {
 
     @Autowired
-    private FullResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktExceptionHandler;
 
     private static Logger jlog = LoggerFactory.getLogger(UserController.class);
     @Autowired
@@ -104,7 +104,7 @@
             user = controller.createUserAccount(values, true);
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         URIParam uri = user.getField(URIParam.class);
         if (uri.hasValues()) {
@@ -123,13 +123,13 @@
                 return Response.ok(JsonUtils.toJSON(object)).build();
             }
             catch (KustvaktException e) {
-                throw kustvaktResponseHandler.throwit(e);
+                throw kustvaktExceptionHandler.throwit(e);
             }
         }
         else {
             jlog.error("Failed creating confirmation and expiry tokens.");
             // EM: why illegal argument when uri fragment/param is self-generated 
-            throw kustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+            throw kustvaktExceptionHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
                     "failed to validate uri parameter",
                     "confirmation fragment");
         }
@@ -157,7 +157,7 @@
             //            controller.updateAccount(user);
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -169,10 +169,10 @@
     public Response confirmRegistration (@QueryParam("uri") String uritoken,
             @Context Locale locale, @QueryParam("user") String username) {
         if (uritoken == null || uritoken.isEmpty())
-            throw kustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+            throw kustvaktExceptionHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
                     "parameter missing", "uri parameter");
         if (username == null || username.isEmpty())
-            throw kustvaktResponseHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
+            throw kustvaktExceptionHandler.throwit(StatusCodes.ILLEGAL_ARGUMENT,
                     "parameter missing", "Username");
 
         try {
@@ -180,7 +180,7 @@
         }
         catch (KustvaktException e) {
             e.printStackTrace();
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -198,7 +198,7 @@
             node = JsonUtils.readTree(json);
         }
         catch (KustvaktException e1) {
-            throw kustvaktResponseHandler.throwit(e1);
+            throw kustvaktExceptionHandler.throwit(e1);
         }
         StringBuilder builder = new StringBuilder();
         String username, email;
@@ -227,7 +227,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Eoxception encountered!", e.string());
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         ObjectNode obj = JsonUtils.createObjectNode();
@@ -237,7 +237,7 @@
             return Response.ok(JsonUtils.toJSON(obj)).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -282,7 +282,7 @@
             return Response.ok(m.toEntity()).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -303,7 +303,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered!", e);
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok(result).build();
     }
@@ -339,7 +339,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered!", e);
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
 
         return Response.ok().build();
@@ -365,7 +365,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered: {}", e.string());
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok(result).build();
     }
@@ -396,7 +396,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered!", e);
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -452,13 +452,13 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered!", e);
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         try {
             return Response.ok(JsonUtils.toJSON(add)).build();
         }
         catch (KustvaktException e) {
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
     }
 
@@ -475,7 +475,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered!", e);
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok().build();
     }
@@ -499,7 +499,7 @@
         }
         catch (KustvaktException e) {
             jlog.error("Exception encountered!", e);
-            throw kustvaktResponseHandler.throwit(e);
+            throw kustvaktExceptionHandler.throwit(e);
         }
         return Response.ok(queryStr).build();
     }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
index 5781520..357ceb5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
@@ -26,7 +26,7 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.service.UserGroupService;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
@@ -50,7 +50,7 @@
 public class UserGroupController {
 
     @Autowired
-    private FullResponseHandler responseHandler;
+    private KustvaktExceptionHandler responseHandler;
     @Autowired
     private UserGroupService service;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
index 1ef676d..d2894c8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
@@ -28,7 +28,7 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.service.VirtualCorpusService;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
@@ -55,7 +55,7 @@
 public class VirtualCorpusController {
 
     @Autowired
-    private FullResponseHandler responseHandler;
+    private KustvaktExceptionHandler responseHandler;
     @Autowired
     private VirtualCorpusService service;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
index aa3b0ad..f28331c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
@@ -27,7 +27,7 @@
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.StringUtils;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 
 /**
  * @author hanl, margaretha
@@ -46,7 +46,7 @@
     private AuthenticationManagerIface authManager;
 
     @Autowired
-    private FullResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktResponseHandler;
 
     @Autowired
     private HttpAuthorizationHandler authorizationHandler;
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
index 118f780..94975d1 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
@@ -19,7 +19,7 @@
 import de.ids_mannheim.korap.security.context.KustvaktContext;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.utils.TimeUtils;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 
 /**
  * @author hanl, margaretha
@@ -38,7 +38,7 @@
     private AuthenticationManagerIface authenticationManager;
 
     @Autowired
-    private FullResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktResponseHandler;
 
     @Override
     public ContainerRequest filter (ContainerRequest request) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
index 107d102..0bb563a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
@@ -13,7 +13,7 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.security.context.TokenContext;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 
 /**
  * @author hanl
@@ -27,7 +27,7 @@
 public class BlockingFilter implements ContainerRequestFilter, ResourceFilter {
 
     @Autowired
-    private FullResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktResponseHandler;
 
     @Override
     public ContainerRequest filter (ContainerRequest request) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
index d47e1da..da8c444 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
@@ -13,7 +13,7 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.security.context.TokenContext;
-import de.ids_mannheim.korap.web.FullResponseHandler;
+import de.ids_mannheim.korap.web.KustvaktExceptionHandler;
 
 /**
  * EM: pretty much identical to {@link BlockingFilter}, should be deleted? 
@@ -30,7 +30,7 @@
         implements ContainerRequestFilter, ResourceFilter {
 
     @Autowired
-    private FullResponseHandler kustvaktResponseHandler;
+    private KustvaktExceptionHandler kustvaktResponseHandler;
 
     @Override
     public ContainerRequest filter (ContainerRequest request) {
diff --git a/full/src/main/resources/default-config.xml b/full/src/main/resources/default-config.xml
index 95b2365..feef295 100644
--- a/full/src/main/resources/default-config.xml
+++ b/full/src/main/resources/default-config.xml
@@ -181,9 +181,13 @@
 		<constructor-arg ref="kustvakt_db" />
 	</bean>
 
-	<bean id="kustvakt_response" class="de.ids_mannheim.korap.web.FullResponseHandler">
+	<bean id="kustvaktResponseHandler" class="de.ids_mannheim.korap.web.KustvaktExceptionHandler">
 		<constructor-arg index="0" name="iface" ref="kustvakt_auditing" />
 	</bean>
+	<bean id="oauth2_exception" class="de.ids_mannheim.korap.web.OAuth2ExceptionHandler">
+		<constructor-arg index="0" name="iface" ref="kustvakt_auditing" />
+	</bean>
+
 
 	<bean id="kustvakt_userdb" class="de.ids_mannheim.korap.handlers.EntityDao">
 		<constructor-arg ref="kustvakt_db" />
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
index 6251147..483c6e2 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
@@ -4,6 +4,10 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+
 import javax.ws.rs.core.MultivaluedMap;
 
 import org.apache.http.entity.ContentType;
@@ -18,6 +22,7 @@
 import com.sun.jersey.api.client.ClientResponse.Status;
 import com.sun.jersey.api.client.UniformInterfaceException;
 import com.sun.jersey.core.util.MultivaluedMapImpl;
+import com.sun.jersey.spi.container.ContainerRequest;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
@@ -38,6 +43,18 @@
     private HttpAuthorizationHandler handler;
     private String username = "OAuth2ClientControllerTest";
 
+    private void checkWWWAuthenticateHeader (ClientResponse response) {
+        Set<Entry<String, List<String>>> headers =
+                response.getHeaders().entrySet();
+
+        for (Entry<String, List<String>> header : headers) {
+            if (header.getKey().equals(ContainerRequest.WWW_AUTHENTICATE)) {
+                assertEquals("Basic realm=\"Kustvakt\"",
+                        header.getValue().get(0));
+            }
+        }
+    }
+    
     private ClientResponse testRegisterConfidentialClient ()
             throws KustvaktException {
 
@@ -70,8 +87,8 @@
         response = testRegisterConfidentialClient();
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         node = JsonUtils.readTree(response.getEntity(String.class));
-        assertEquals(StatusCodes.CLIENT_REGISTRATION_FAILED,
-                node.at("/errors/0/0").asInt());
+        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+                node.at("/error").asText());
 
         testDeregisterClientIncorrectCredentials(clientId);
         testDeregisterConfidentialClient(clientId, clientSecret);
@@ -161,7 +178,6 @@
                 .entity(form).delete(ClientResponse.class);
 
         String entity = response.getEntity(String.class);
-//        System.out.println(entity);
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
         
         JsonNode node = JsonUtils.readTree(entity);
@@ -169,5 +185,7 @@
                 node.at("/error").asText());
         assertEquals("Invalid client credentials.",
                 node.at("/error_description").asText());
+        
+        checkWWWAuthenticateHeader(response);
     }
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
index f52c883..794ea6b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
@@ -1,12 +1,17 @@
 package de.ids_mannheim.korap.web.controller;
 
+import static org.junit.Assert.assertEquals;
+
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
+import org.apache.oltu.oauth2.common.error.OAuthError;
 import org.apache.oltu.oauth2.common.message.types.GrantType;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
 import com.sun.jersey.api.client.ClientHandlerException;
 import com.sun.jersey.api.client.ClientResponse;
@@ -17,6 +22,7 @@
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.utils.JsonUtils;
 
 /**
  * @author margaretha
@@ -34,9 +40,8 @@
             KustvaktException {
 
         MultivaluedMap<String, String> form = new MultivaluedMapImpl();
-//        form.add("grant_type", "blahblah");
-        form.add("grant_type", GrantType.REFRESH_TOKEN.name());
-        
+        form.add("grant_type", "blahblah");
+
         ClientResponse response = resource().path("oauth2").path("token")
                 .header(Attributes.AUTHORIZATION,
                         handler.createBasicAuthorizationHeaderValue(username,
@@ -46,8 +51,15 @@
                         ContentType.APPLICATION_FORM_URLENCODED)
                 .entity(form).post(ClientResponse.class);
 
-        System.out.println(response.getStatus());
-        System.out.println(response.getEntity(String.class));
+        String entity = response.getEntity(String.class);
+//        System.out.println(entity);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals("blahblah is not supported.",
+                node.get("error_description").asText());
+        assertEquals(OAuthError.TokenResponse.UNSUPPORTED_GRANT_TYPE,
+                node.get("error"));
     }
 
 }
diff --git a/full/src/test/resources/test-config.xml b/full/src/test/resources/test-config.xml
index 1757481..66b6c97 100644
--- a/full/src/test/resources/test-config.xml
+++ b/full/src/test/resources/test-config.xml
@@ -181,7 +181,10 @@
 		<constructor-arg ref="kustvakt_db" />
 	</bean>
 
-	<bean id="kustvakt_response" class="de.ids_mannheim.korap.web.FullResponseHandler">
+	<bean id="kustvaktExceptionHandler" class="de.ids_mannheim.korap.web.KustvaktExceptionHandler">
+		<constructor-arg index="0" name="iface" ref="kustvakt_auditing" />
+	</bean>
+	<bean id="oauth2ExceptionHandler" class="de.ids_mannheim.korap.web.OAuth2ExceptionHandler">
 		<constructor-arg index="0" name="iface" ref="kustvakt_auditing" />
 	</bean>