Skip to content

Commit

Permalink
Added README. Added Chain annotation to facilitate filters.
Browse files Browse the repository at this point in the history
  • Loading branch information
noboomu committed May 8, 2017
1 parent c6ee584 commit 084479b
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 20 deletions.
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# PROTEUS

An extremely lightweight, flexible and fast [Swagger](http://swagger.io/) first REST API framework atop [Undertow](http://undertow.io).
A great deal of inspiration came from working with the following excellent projects: [Play](http://playframework.com), [Jooby](http://jooby.org), and [light-4j](https://github.com/networknt/light-4j).

### Motivation
- Several years of working with the [Play](http://playframework.com) framework convinced us there had to be a better way.
- We faced a Goldilocks Crisis with the existing alternatives: [Jooby](http://jooby.org) did too much, [light-4j](https://github.com/networknt/light-4j) didn't do quite enough.
- We needed a framework that enabled us to write clean MVC REST controllers that created Swagger docs we could plug directly into the existing [codegen](https://github.com/swagger-api/swagger-codegen) solutions.
- We needed a framework with minimal overhead and performance at or near that of raw [Undertow](http://undertow.io).

### Built With
- [Undertow](http://undertow.io) (server)
- [Guice](https://github.com/google/guice) (di)
- [Java Runtime Compiler](https://github.com/OpenHFT/Java-Runtime-Compiler) (runtime generated class compilation)
- [javapoet](https://github.com/square/javapoet) (runtime class generation)
- [Jackson](https://github.com/FasterXML/jackson-dataformat-xml) (xml)
- [jsoniter](http://jsoniter.com/) (json)
- [Logback](https://logback.qos.ch/) (logging)
- [Typesafe Config](https://github.com/typesafehub/config) (config)
- [Swagger](http://swagger.io/) (annotations and swagger spec)
- [jax-rs](http://docs.oracle.com/javaee/6/api/javax/ws/rs/package-summary.html) (annotations only)

### Dependencies
* [JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
* [Maven 3](http://maven.apache.org/)

### Setup
- We are very impressed by what Jooby has done with server configuration
- Parameters are all configured in the ```conf/application.conf``` file
- Proteus applications generally have a main method that creates an instance of ```io.sinistral.proteus.Application```
- The user adds ```Service``` and ```Module``` classes to the application instance via ```addService``` and ```addModule``` methods prior to calling ```start```

### Getting Started
- COMING SOON

### Running

mvn exec:exec


10 changes: 0 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.22.0-CR1</version>
</dependency>

<dependency>
<groupId>io.swagger</groupId>
Expand Down Expand Up @@ -323,11 +318,6 @@
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>io.sinistral</groupId>
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/io/sinistral/proteus/ProteusApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

import io.sinistral.proteus.modules.ConfigModule;
import io.sinistral.proteus.server.endpoints.EndpointInfo;
import io.sinistral.proteus.server.handlers.DefaultHttpHandler;
import io.sinistral.proteus.server.handlers.ServerDefaultHttpHandler;
import io.sinistral.proteus.server.handlers.HandlerGenerator;
import io.sinistral.proteus.services.AssetsService;
import io.sinistral.proteus.services.SwaggerService;
Expand Down Expand Up @@ -116,8 +116,8 @@ public void start()

if( rootHandlerClass == null && rootHandler == null )
{
log.warn("No root handler class or root HttpHandler was specified, using default DefaultHttpHandler.");
rootHandlerClass = DefaultHttpHandler.class;
log.warn("No root handler class or root HttpHandler was specified, using default ServerDefaultHttpHandler.");
rootHandlerClass = ServerDefaultHttpHandler.class;
}

log.info("Starting services...");
Expand Down Expand Up @@ -350,7 +350,7 @@ public static void main(String[] args)

app.addService(AssetsService.class);

app.setRootHandlerClass(DefaultHttpHandler.class);
app.setRootHandlerClass(ServerDefaultHttpHandler.class);

app.start();

Expand Down
26 changes: 26 additions & 0 deletions src/main/java/io/sinistral/proteus/annotations/Chain.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
*
*/
package io.sinistral.proteus.annotations;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import io.undertow.server.HandlerWrapper;

@Retention(RUNTIME)
@Target({ TYPE, METHOD })
/**
* @author jbauer
*
*/
public @interface Chain
{
Class<? extends HandlerWrapper>[] value();
}


Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import io.sinistral.proteus.server.ServerResponse;
import io.sinistral.proteus.server.endpoints.EndpointInfo;
import io.swagger.annotations.Api;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.RoutingHandler;
Expand Down Expand Up @@ -750,7 +751,7 @@ else if(t.equals(HttpServerExchange.class) || t.equals(ServerRequest.class))

endpointInfo.setControllerMethod( m.getName());

String methodName = String.format("%c%s%sHandler", Character.toLowerCase(clazz.getSimpleName().charAt(0)), clazz.getSimpleName().substring(1, clazz.getSimpleName().length()), StringUtils.capitalize(m.getName()));
String handlerName = String.format("%c%s%sHandler", Character.toLowerCase(clazz.getSimpleName().charAt(0)), clazz.getSimpleName().substring(1, clazz.getSimpleName().length()), StringUtils.capitalize(m.getName()));

TypeSpec.Builder handlerClassBuilder = TypeSpec.anonymousClassBuilder("").addSuperinterface(httpHandlerClass);

Expand Down Expand Up @@ -1025,12 +1026,43 @@ else if(producesContentType.contains(MediaType.TEXT_HTML))



FieldSpec handlerField = FieldSpec.builder(httpHandlerClass, methodName, Modifier.FINAL).initializer("$L", handlerClassBuilder.build()).build();
FieldSpec handlerField = FieldSpec.builder(httpHandlerClass, handlerName, Modifier.FINAL).initializer("$L", handlerClassBuilder.build()).build();

initBuilder.addCode("$L\n", handlerField.toString());

Optional<io.sinistral.proteus.annotations.Chain> wrapAnnotation = Optional.ofNullable(m.getAnnotation(io.sinistral.proteus.annotations.Chain.class));

if( wrapAnnotation.isPresent() )
{
io.sinistral.proteus.annotations.Chain w = wrapAnnotation.get();

Class<? extends HandlerWrapper> wrapperClasses[] = w.value();

initBuilder.addStatement("$T currentHandler = $L", HttpHandler.class, handlerName);


for( int i = 0; i < wrapperClasses.length; i++ )
{
Class<? extends HandlerWrapper> wrapperClass = wrapperClasses[i];

String wrapperName = generateFieldName(wrapperClass.getCanonicalName());

initBuilder.addStatement("$T $L = new $T()", wrapperClass,wrapperName, wrapperClass);

initBuilder.addStatement("$L.add(io.undertow.util.Methods.$L,$S,$L)", "router", httpMethod, methodPath, methodName);
initBuilder.addStatement("currentHandler = $L.wrap($L)", wrapperName, "currentHandler");

}

initBuilder.addStatement("$L.add(io.undertow.util.Methods.$L,$S,$L)", "router", httpMethod, methodPath, "currentHandler");

}
else
{
initBuilder.addStatement("$L.add(io.undertow.util.Methods.$L,$S,$L)", "router", httpMethod, methodPath, handlerName);
}



initBuilder.addCode("$L", "\n");

registeredEndpoints.add(endpointInfo);
Expand Down Expand Up @@ -1315,11 +1347,34 @@ public static String typeLiteralNameForType(Type type)
erasedTypeName = erasedParts[0];
}

typeName = String.format("%s%s", Character.toLowerCase(erasedTypeName.charAt(0)), erasedTypeName.substring(1, erasedTypeName.length()));
typeName = generateFieldName(erasedTypeName);


return typeName;
}

public static String generateFieldName(String name)
{
String[] parts = name.split("\\.");

StringBuilder sb = new StringBuilder();

for( int i = 0; i < parts.length; i++ )
{
String part = parts[i];

if(i == 0)
{
sb.append(String.format("%s%s", Character.toLowerCase(part.charAt(0)), part.substring(1, part.length())));
}
else
{
sb.append(String.format("%s%s", Character.toUpperCase(part.charAt(0)), part.substring(1, part.length())));
}
}

return sb.toString();
}

public static void generateTypeLiteral(MethodSpec.Builder builder, Type type, String name)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
/**
* @author jbauer
*/
public class DefaultHttpHandler implements HttpHandler
public class ServerDefaultHttpHandler implements HttpHandler
{

@Inject(optional=true)
Expand All @@ -33,7 +33,7 @@ public class DefaultHttpHandler implements HttpHandler


@Inject
public DefaultHttpHandler(Config config)
public ServerDefaultHttpHandler(Config config)
{
Config globalHeaders = config.getConfig("globalHeaders");

Expand Down

0 comments on commit 084479b

Please sign in to comment.