diff --git a/.gitignore b/.gitignore
index 9eb4605..585248f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ bin
.cache-tests
/proteus/
/pom.xml.versionsBackup
+.factorypath
diff --git a/conf/logback.xml b/conf/logback.xml
index 1a61aa3..e5e2656 100644
--- a/conf/logback.xml
+++ b/conf/logback.xml
@@ -5,109 +5,54 @@
true
- %date{ISO8601} %highlight(%-5level) [%boldCyan(%logger)] [%boldYellow(%method %F) ] - %boldWhite(%message) %n %red(%ex)
+ %date{ISO8601} %highlight(%-5level) [%boldCyan(%logger)]
+ [%boldYellow(%method %F) ] - %boldWhite(%message) %n %red(%ex)
-
-
-
-
-
+
+
-
+
-
- io.sinistral.proteus.services
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
-
-
+
-
+
-
-
-
-
-
+
-
-
+
+
+
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java b/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java
index 0da34d3..00e55e8 100644
--- a/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java
+++ b/src/main/java/io/sinistral/proteus/modules/ApplicationModule.java
@@ -14,7 +14,9 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import com.google.common.util.concurrent.Service;
@@ -58,17 +60,39 @@ protected void configure()
{
this.binder().requestInjection(this);
-
+
+ this.bindMappers();
+
RoutingHandler router = new RoutingHandler();
+ try
+ {
+ String className = config.getString("application.defaultResponseListener");
+ log.info("Installing DefaultResponseListener " + className);
+ Class extends DefaultResponseListener> clazz = (Class extends DefaultResponseListener>) Class.forName(className);
+ this.bind(DefaultResponseListener.class).to(clazz).in(Singleton.class);
+ } catch (Exception e)
+ {
+ this.binder().addError(e);
+ log.error(e.getMessage(), e);
+ }
+
try
{
String className = config.getString("application.fallbackHandler");
log.info("Installing FallbackListener " + className);
+
Class extends HttpHandler> clazz = (Class extends HttpHandler>) Class.forName(className);
- router.setFallbackHandler(clazz.newInstance());
+
+ HttpHandler fallbackHandler = clazz.newInstance();
+
+ this.binder().requestInjection(fallbackHandler);
+
+ router.setFallbackHandler(fallbackHandler);
+
} catch (Exception e)
{
+ this.binder().addError(e);
log.error(e.getMessage(), e);
}
@@ -76,16 +100,7 @@ protected void configure()
this.bind(ApplicationModule.class).toInstance(this);
- try
- {
- String className = config.getString("application.defaultResponseListener");
- log.info("Installing DefaultResponseListener " + className);
- Class extends DefaultResponseListener> clazz = (Class extends DefaultResponseListener>) Class.forName(className);
- this.bind(DefaultResponseListener.class).to(clazz).in(Singleton.class);
- } catch (Exception e)
- {
- log.error(e.getMessage(), e);
- }
+
this.bind(new TypeLiteral>>()
{
@@ -103,8 +118,7 @@ protected void configure()
{
}).annotatedWith(Names.named("registeredHandlerWrappers")).toInstance(registeredHandlerWrappers);
-
- this.bindMappers();
+
}
@@ -113,12 +127,15 @@ protected void configure()
*/
public void bindMappers()
{
- this.bind(XmlMapper.class).toInstance(new XmlMapper());
-
-// JsonIterator.setMode(DecodingMode.DYNAMIC_MODE_AND_MATCH_FIELD_WITH_HASH);
-// JsonStream.setMode(EncodingMode.DYNAMIC_MODE);
-// JsoniterAnnotationSupport.enable();
+ JacksonXmlModule xmlModule = new JacksonXmlModule();
+ xmlModule.setDefaultUseWrapper(false);
+
+ XmlMapper xmlMapper = new XmlMapper(xmlModule);
+ xmlMapper.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION);
+
+ this.bind(XmlMapper.class).toInstance(xmlMapper);
+
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);
diff --git a/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java b/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java
index febce1a..00fc792 100644
--- a/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java
+++ b/src/main/java/io/sinistral/proteus/server/handlers/ServerDefaultResponseListener.java
@@ -51,22 +51,32 @@ public boolean handleDefaultResponse(HttpServerExchange exchange)
return false;
}
- if (exchange.getStatusCode() >= 400) {
+ final int statusCode = exchange.getStatusCode();
+
+ if (statusCode >= 400) {
+ final Map errorMap = new HashMap<>();
+
+ final String path = exchange.getRelativePath();
+
Throwable throwable = exchange.getAttachment(DefaultResponseListener.EXCEPTION);
if( throwable == null )
{
- throwable = new Exception("An unknown error occured");
+ final String reason = StatusCodes.getReason(statusCode);
+
+ throwable = new Exception(reason);
}
-
- Map errorMap = new HashMap<>();
-
+
errorMap.put("exceptionClass", throwable.getClass().getName());
errorMap.put("message", throwable.getMessage());
- log.error(throwable.getMessage(),throwable);
+ errorMap.put("path", path);
+
+ errorMap.put("code", Integer.toString(statusCode));
+
+ log.error(throwable.getMessage() + " at " + path,throwable);
if( throwable.getStackTrace() != null )
{
diff --git a/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java b/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java
index b98df25..1b317ad 100644
--- a/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java
+++ b/src/main/java/io/sinistral/proteus/server/handlers/ServerFallbackHandler.java
@@ -3,23 +3,82 @@
*/
package io.sinistral.proteus.server.handlers;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Inject;
+
+import io.sinistral.proteus.server.predicates.ServerPredicates;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.Headers;
+import io.undertow.util.StatusCodes;
/**
* @author jbauer
- *
*/
public class ServerFallbackHandler implements HttpHandler
-{
-
- @Override
- public void handleRequest(HttpServerExchange exchange) throws Exception
+{
+ private class Message {
+
+ @SuppressWarnings("unused")
+ public final Integer statusCode;
+ @SuppressWarnings("unused")
+ public final String reason;
+
+ /**
+ * @param statusCode
+ * @param reason
+ */
+ public Message(Integer statusCode, String reason)
+ {
+ this.statusCode = statusCode;
+ this.reason = reason;
+ }
+ }
+
+ @Inject
+ protected XmlMapper xmlMapper;
+
+ @Inject
+ protected ObjectMapper objectMapper;
+
+ @Override
+ public void handleRequest(HttpServerExchange exchange) throws Exception
+ {
+ final int statusCode = 404;
+
+ exchange.setStatusCode(statusCode);
+
+ final String responseBody;
+
+ final String reason = StatusCodes.getReason(statusCode);
+
+ if (ServerPredicates.ACCEPT_JSON_PREDICATE.resolve(exchange))
+ {
+ responseBody = objectMapper.writeValueAsString(new Message(statusCode,reason));
+ exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, javax.ws.rs.core.MediaType.APPLICATION_JSON);
+ }
+ else if (ServerPredicates.ACCEPT_XML_PREDICATE.resolve(exchange))
+ {
+ responseBody = xmlMapper.writeValueAsString(new Message(statusCode,reason));
+ exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, javax.ws.rs.core.MediaType.APPLICATION_XML);
+ }
+ else if (ServerPredicates.ACCEPT_HTML_PREDICATE.resolve(exchange))
+ {
+ responseBody = "Error" + statusCode + " - " + reason + "";
+ exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, javax.ws.rs.core.MediaType.TEXT_HTML);
+ }
+ else
{
- exchange.setStatusCode(404);
- exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
- exchange.getResponseSender().send("Page Not Found!!");
-
- }
+ responseBody = statusCode + " - " + reason;
+ exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, javax.ws.rs.core.MediaType.TEXT_PLAIN);
+ }
+
+ exchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, "" + responseBody.length());
+ exchange.getResponseSender().send(responseBody);
+
+
+
+ }
}
diff --git a/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java b/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java
index c559274..ff08211 100644
--- a/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java
+++ b/src/main/java/io/sinistral/proteus/server/predicates/ServerPredicates.java
@@ -24,21 +24,19 @@ public class ServerPredicates
public static final String XML_REGEX = "^(application\\/(xml|xhtml\\+xml)|text\\/xml)(;.*)?$";
+ public static final String HTML_REGEX = "^(text\\/html)(;.*)?$";
+
public static final String TEXT_REGEX = "^(text\\/plain)(;.*)?$";
public static final Predicate JSON_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), JSON_REGEX);
public static final Predicate XML_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), XML_REGEX);
-
- //public static final Predicate JSON_PREDICATE = Predicates.contains(ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), MediaType.APPLICATION_JSON.contentType(), MediaType.APPLICATION_JSON.withCharset("utf-8"));
- //public static final Predicate XML_PREDICATE = Predicates.contains(ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), MediaType.APPLICATION_XML.contentType(),MediaType.APPLICATION_XML.withCharset("UTF-8"));
-
+ public static final Predicate HTML_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.CONTENT_TYPE), HTML_REGEX);
public static final Predicate WILDCARD_PREDICATE = Predicates.contains(ExchangeAttributes.requestHeader(Headers.ACCEPT), MediaType.ANY.contentType());
public static final Predicate NO_WILDCARD_PREDICATE = Predicates.not(Predicates.contains(ExchangeAttributes.requestHeader(Headers.ACCEPT), MediaType.ANY.contentType()));
- //public static final Predicate ACCEPT_JSON_PREDICATE = Predicates.contains(ExchangeAttributes.requestHeader(Headers.ACCEPT), MediaType.APPLICATION_JSON.contentType(),MediaType.APPLICATION_JSON.withCharset("UTF-8").toString());
public static final Predicate ACCEPT_JSON_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.ACCEPT), JSON_REGEX);
- public static final Predicate ACCEPT_XML_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.ACCEPT), XML_REGEX);;
- public static final Predicate ACCEPT_TEXT_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.ACCEPT), TEXT_REGEX);;
-//public static final Predicate ACCEPT_XML_PREDICATE = Predicates.contains(ExchangeAttributes.requestHeader(Headers.ACCEPT), MediaType.APPLICATION_XML.contentType(),MediaType.APPLICATION_XML.withCharset("UTF-8").toString());
+ public static final Predicate ACCEPT_XML_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.ACCEPT), XML_REGEX);
+ public static final Predicate ACCEPT_HTML_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.ACCEPT), HTML_REGEX);
+ public static final Predicate ACCEPT_TEXT_PREDICATE = Predicates.regex(ExchangeAttributes.requestHeader(Headers.ACCEPT), TEXT_REGEX);
public static final Predicate ACCEPT_XML_EXCLUSIVE_PREDICATE = Predicates.and(ACCEPT_XML_PREDICATE, NO_WILDCARD_PREDICATE );
public static final Predicate MAX_CONTENT_SIZE_PREDICATE = new MaxRequestContentLengthPredicate.Builder().build(Collections.singletonMap("value", 0L));
public static final Predicate STRING_BODY_PREDICATE = Predicates.and(Predicates.or(JSON_PREDICATE,XML_PREDICATE), MAX_CONTENT_SIZE_PREDICATE );
diff --git a/src/main/resources/io/sinistral/proteus/swagger/index.html b/src/main/resources/io/sinistral/proteus/swagger/index.html
index f24cc4f..7e96476 100644
--- a/src/main/resources/io/sinistral/proteus/swagger/index.html
+++ b/src/main/resources/io/sinistral/proteus/swagger/index.html
@@ -7,7 +7,6 @@
{{ title }}
-