Rest2Typescript

This plugin generates Typescript files for using your Spring REST-@Controllers. Every method annotated with @RequestMapping will get a corresponding method in the Typescript controller and all the required Types for in and output are exported as interface, so you can call it typesafe.

What is this plugin meant to do?

  • Let you call your REST Services from Typescript without manually writing boilerplate code
  • Keep your Typescript types in sync with the backend

How it works

  • The Reflections API https://github.com/ronmamo/reflections is used to locate all classes annotated with the Spring @Controller annotation
  • For each Controller an Typescipt object is created with the same name.
  • For each method of the controller annotated with @RequestMapping, the object gets a corresponding method which calls the Controller via ajax with jquery

Example

Assume you have the following controller:

@Controller
public class SampleController {


    @RequestMapping("sayHello")
    public void sayHello() {
        System.out.println("Hello");
    }

    @RequestMapping("returnHello")
    public String returnHello() {
        return "Hello";
    }

    @RequestMapping("returnStuff")
    public String returnStuff(@RequestParam String stuff) {
        return "Hello "+stuff;
    }

    public static @Data class ReturnExample {
        final String name;
        final double price;
    }

    @RequestMapping("returnObject")
    public ReturnExample returnObject() {
        return new ReturnExample("bla", 42d);
    }

    public static @Data class ComplexInput {
        final String name;
        final double price;
        final String[] array;
    }

    @PostMapping("/exampleWithPost")
    public String postExampleWithRequestBody(@RequestBody ComplexInput complexInput) {
        return "Your example contains "+name;
    }

}

the Plugin will generate for you:

/// <reference path="node_modules/@types/jquery/index.d.ts" />;

export let SampleController = {
    returnHello: function(success: (result: string)=> void){
        return $.getJSON(
            "returnHello",
            {
            },
            success
        );
    },
    returnObject: function(success: (result: ReturnExample)=> void){
        return $.getJSON(
            "returnObject",
            {
            },
            success
        );
    },
    returnStuff: function(stuff: string,success: (result: string)=> void){
        return $.getJSON(
            "returnStuff",
            {
                stuff: stuff,
            },
            success
        );
    },
    sayHello: function(success: ()=> void){
        return $.getJSON(
            "sayHello",
            {
            },
            success
        );
    },
    postExampleWithRequestBody: function(complexInput: ComplexInput): Promise<String>{
        return new Promise(resolve => {$.ajax({
            type: "POST",
            url: "/exampleWithPost",
            data: JSON.stringify(complexInput),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: resolve
            }
        );
    });},
};

export interface ReturnExample {
    name: string
    price: number
}

export interface ComplexInput {
    name: string ;
    price: number;
    array: string[];
}

Installation

You can then add the plugin to your pom.xml and hook it to the process-classes phase, so it will create the Typescript File src/main/resources/META-INF/resources/ts/javatypes.ts on every build

<plugin>
    <groupId>de.thomas-oster</groupId>
    <artifactId>rest2typescript-maven-plugin</artifactId>
    <version>1.0</version>
    <configuration>
        <generatedFile>src/main/resources/META-INF/resources/ts/javatypes.ts</generatedFile>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>generate
                </goal>
            </goals>
            <phase>process-classes</phase>
        </execution>
    </executions>
</plugin>

If you have problems, because all your parameters are called arg0, arg1 etc. in the typescript files, you need to tell the compiler to include the parameter names in the java bytecode with the -params flag:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <source>11</source>
        <target>11</target>
        <!-- needed in order for rest2typescript to get the right names -->
        <fork>true</fork>
        <compilerArgument>-parameters</compilerArgument>
    </configuration>
</plugin>

You can also call mvn rest2typescript:generate from the command line

Limitations / TODOs

  • We do not yet support @RequestMapping on the class level
  • We do not yet support @PathParameter