Skip to content

Commit

Permalink
[break][Undertow] Rewrite conjure-undertow API (#260)
Browse files Browse the repository at this point in the history
## All implementation has moved to the runtime module
* `conjure-undertow-lib` only contains interfaces.
* `ServiceContext` -> `UndertowRuntime`
* `StringDeserializers` -> `UndertowRuntime.plainSerDe()`
* `Auth.cookie/header` -> `UndertowRuntime.auth().cookie/header`

**Rationale**: All runtime behavior should be updated in lock step in `conjure-java-runtime`, this change allows the undertow runtime to behave similarly to jersey.

## Renamed Service to UndertowService
Registering generated service implementations using `.api(Service)` failed to make it clear what `Service` was. `.api(UndertowService)` is immediately understandable.

## `UndertowService` creates a list of `Endpoint`
`Registerable` and `EndpointRegistry` are no longer needed in this simplified model. Generated code is easier to understand and only contains one level of nested inner classes.

## Serializers and Deserializers are typed
Serializer and Deserializer objects are created eagerly when Endpoints are constructed in order to match the conjure specification more closely. Each endpoint receives exactly one body type, and returns exactly one type. 

This avoids unnecessary type mapping for each request.

## Immutable UndertowHandler
Endpoints must be added to the `UndertowHandler.Builder` before a `HttpHandler` is created to ensure behavior remains constant once a server has started.

## Example generated `EmptyPathServiceEndpoints.java`

Note that the output is more verbose than previous versions, however it's also less complex in both legibility runtime cost.

```java
@generated("com.palantir.conjure.java.services.UndertowServiceHandlerGenerator")
public final class EmptyPathServiceEndpoints implements UndertowService {
    private final EmptyPathService delegate;

    private EmptyPathServiceEndpoints(EmptyPathService delegate) {
        this.delegate = delegate;
    }

    public static UndertowService of(EmptyPathService delegate) {
        return new EmptyPathServiceEndpoints(delegate);
    }

    @OverRide
    public List<Endpoint> endpoints(UndertowRuntime runtime) {
        return ImmutableList.of(new EmptyPathEndpoint(runtime, delegate));
    }

    private static final class EmptyPathEndpoint implements HttpHandler, Endpoint {
        private final UndertowRuntime runtime;

        private final EmptyPathService delegate;

        private final Serializer<Boolean> serializer;

        EmptyPathEndpoint(UndertowRuntime runtime, EmptyPathService delegate) {
            this.runtime = runtime;
            this.delegate = delegate;
            this.serializer = runtime.bodySerDe().serializer(new TypeToken<Boolean>() {});
        }

        @OverRide
        public void handleRequest(HttpServerExchange exchange) throws IOException {
            boolean result = delegate.emptyPath();
            serializer.serialize(result, exchange);
        }

        @OverRide
        public HttpString method() {
            return Methods.GET;
        }

        @OverRide
        public String template() {
            return "/";
        }

        @OverRide
        public String serviceName() {
            return "EmptyPathService";
        }

        @OverRide
        public String name() {
            return "emptyPath";
        }

        @OverRide
        public HttpHandler handler() {
            return this;
        }
    }
}
```
  • Loading branch information
carterkozak authored and bulldozer-bot[bot] committed Mar 8, 2019
1 parent fd93162 commit aefca4e
Show file tree
Hide file tree
Showing 48 changed files with 3,891 additions and 2,205 deletions.
Original file line number Diff line number Diff line change
@@ -1,58 +1,78 @@
package com.palantir.product;

import com.google.common.collect.ImmutableList;
import com.palantir.conjure.java.undertow.lib.Endpoint;
import com.palantir.conjure.java.undertow.lib.EndpointRegistry;
import com.palantir.conjure.java.undertow.lib.Registrable;
import com.palantir.conjure.java.undertow.lib.SerializerRegistry;
import com.palantir.conjure.java.undertow.lib.Service;
import com.palantir.conjure.java.undertow.lib.ServiceContext;
import com.palantir.conjure.java.undertow.lib.Serializer;
import com.palantir.conjure.java.undertow.lib.TypeMarker;
import com.palantir.conjure.java.undertow.lib.UndertowRuntime;
import com.palantir.conjure.java.undertow.lib.UndertowService;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import io.undertow.util.Methods;
import java.io.IOException;
import java.util.List;
import javax.annotation.Generated;

@Generated("com.palantir.conjure.java.services.UndertowServiceHandlerGenerator")
public final class EmptyPathServiceEndpoints implements Service {
public final class EmptyPathServiceEndpoints implements UndertowService {
private final UndertowEmptyPathService delegate;

private EmptyPathServiceEndpoints(UndertowEmptyPathService delegate) {
this.delegate = delegate;
}

public static Service of(UndertowEmptyPathService delegate) {
public static UndertowService of(UndertowEmptyPathService delegate) {
return new EmptyPathServiceEndpoints(delegate);
}

@Override
public Registrable create(ServiceContext context) {
return new EmptyPathServiceRegistrable(context, delegate);
public List<Endpoint> endpoints(UndertowRuntime runtime) {
return ImmutableList.of(new EmptyPathEndpoint(runtime, delegate));
}

private static final class EmptyPathServiceRegistrable implements Registrable {
private static final class EmptyPathEndpoint implements HttpHandler, Endpoint {
private final UndertowRuntime runtime;

private final UndertowEmptyPathService delegate;

private final SerializerRegistry serializers;
private final Serializer<Boolean> serializer;

EmptyPathEndpoint(UndertowRuntime runtime, UndertowEmptyPathService delegate) {
this.runtime = runtime;
this.delegate = delegate;
this.serializer = runtime.bodySerDe().serializer(new TypeMarker<Boolean>() {});
}

@Override
public void handleRequest(HttpServerExchange exchange) throws IOException {
boolean result = delegate.emptyPath();
serializer.serialize(result, exchange);
}

@Override
public HttpString method() {
return Methods.GET;
}

private EmptyPathServiceRegistrable(
ServiceContext context, UndertowEmptyPathService delegate) {
this.serializers = context.serializerRegistry();
this.delegate =
context.serviceInstrumenter()
.instrument(delegate, UndertowEmptyPathService.class);
@Override
public String template() {
return "/";
}

@Override
public void register(EndpointRegistry endpointRegistry) {
endpointRegistry.add(
Endpoint.get("/", "EmptyPathService", "emptyPath"), new EmptyPathHandler());
public String serviceName() {
return "UndertowEmptyPathService";
}

private class EmptyPathHandler implements HttpHandler {
@Override
public void handleRequest(HttpServerExchange exchange) throws IOException {
boolean result = delegate.emptyPath();
serializers.serialize(result, exchange);
}
@Override
public String name() {
return "emptyPath";
}

@Override
public HttpHandler handler() {
return this;
}
}
}
Loading

0 comments on commit aefca4e

Please sign in to comment.