New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Principled Java code generation #36

Open
blast-hardcheese opened this Issue Mar 26, 2018 · 4 comments

Comments

Projects
None yet
2 participants
@blast-hardcheese
Collaborator

blast-hardcheese commented Mar 26, 2018

Jotting down some thoughts for the future. The core underlying concept of guardrail seems doable in Java; one challenge would be maintaining the flexibility of the various typeclasses without global registries. Explicit value passing and typechecking responses.

The biggest advantage I see for providing this would be to permit an easier migration path from existing Java services into Scala, by first following best practices isolating the business logic from the web framework and using generated models+encoders/decoders for all communication, then migrating the business logic piecemeal into Scala by using scala-java8-compat to adapt down to toCompletableFuture.

@blast-hardcheese

This comment has been minimized.

Collaborator

blast-hardcheese commented Mar 26, 2018

Some code to throw darts at:

interface GetUserResponse {
    int statusCode;
}

class GetUserResponseBuilder() {
    class GetUserResponseOk() extends GetUserResponse {
        int statusCode = 200;
    }

    class GetUserResponseBadRequest(String message) extends GetUserResponse {
        int statusCode = 400;
        String getMessage() {
            return message;
        }
    }

    GetUserResponse Ok() {
        return new GetUserResponseOk();
    }

    GetUserResponse BadRequest(String message) {
        return new GetUserResponseBadRequest(message);
    }
}

interface FooUser {
    CompletableFuture<GetUserResponse> getUser(GetUserResponseBuilder respond, String username);
}

new FooUser {
    CompletableFuture<GetUserResponse> getUser(GetUserResponseBuilder respond, String username) {
        CompletableFuture<GetUserResponse> result = new CompletableFuture<>();
        if (username == "foo") {
            result.complete(respond.Ok());
        } else {
            result.complete(respond.BadRequest("Unknown user: " + username));
        }
        return result;
    }
}
@ktoso

This comment has been minimized.

Collaborator

ktoso commented Mar 27, 2018

Yeap, this would be pretty great to grow adoption and to get people to be able to move/switch if they wish to do so...

I think it'd be amazing to have both languages covered, and all these tools expose Routes, since then one can literally combine "anything they want" into such routes...

For reference, this is the style that akka-grpc generates for Java: https://github.com/akka/akka-grpc/blob/master/plugin-tester-java/src/main/java/io/grpc/examples/helloworld/GreeterServiceImpl.java
Similar enough btw... :-)

@ktoso

This comment has been minimized.

Collaborator

ktoso commented Mar 28, 2018

We discussed some more -- it would be preferable to avoid "string concating style" but rather work on ASTs... If you have a preference which APIs to use posting here would help @blast-hardcheese, thanks!

@blast-hardcheese

This comment has been minimized.

Collaborator

blast-hardcheese commented Apr 5, 2018

I've been eyeing https://github.com/javaparser/javaparser for some time.

A small list of the benefits of having a full AST for target languages are:

  • Impossible to accidentally generate invalid syntax
  • It's possible to write tests in a very natural way, then parse the code to get the AST back out
  • A good AST library should have support for different variants of the target language without having to write it ourselves

A small overview of work to be done:

  • Move the rest of the Scala-specific stuff out of SwaggerUtil
  • Split AkkaHttp into AkkaHttpScalaDsl and AkkaHttpJavaDsl
  • Compile the output from the framework generator into a selectable language generator instead of going directly from framework generator to Target

The last two points are moving towards a particular goal -- It should conceivably be possible to use the javadsl from Scala and possibly the scaladsl from Java, although I'd be less focused on that.

The motivation behind this is that even though most of the underlying types are compatible, treating them as separate http frameworks should keep us from building too tight of coupling between the framework and the language.

Even if this isn't achieved with the first iteration, as more frameworks are added (scalatra, server support for http4s) and other languages (eta being a primary target from a safety perspective, languages like java, groovy, and jruby being offered as gateways to writing safer code) this should be a guiding principle.

@blast-hardcheese blast-hardcheese referenced this issue Nov 8, 2018

Open

Language ambivalence #133

1 of 5 tasks complete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment