DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Spring Boot - How To Use Native SQL Queries | Restful Web Services
  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)
  • RESTful Web Services: How To Create a Context Path for Spring Boot Application or Web Service
  • Aggregating REST APIs Calls Using Apache Camel

Trending

  • Advancing Your Software Engineering Career in 2025
  • Implementing Explainable AI in CRM Using Stream Processing
  • Designing a Java Connector for Software Integrations
  • Securing the Future: Best Practices for Privacy and Data Governance in LLMOps
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring REST TypeScript Generator

Spring REST TypeScript Generator

By 
Tomasz Wozniak user avatar
Tomasz Wozniak
·
Updated Dec. 05, 19 · Tutorial
Likes (17)
Comment
Save
Tweet
Share
52.9K Views

Join the DZone community and get the full member experience.

Join For Free

dandelions-in-spring

I have been a backend developer for eighteen years without writing a single line of code on the client-side, but with the dawn of single-page applications, my cooperation with web developers got closer. I started to observe their work with interest. There are so many exciting possibilities on the frontend side. It made me consider to build up my technology stack and become a full stack developer.

I noticed that web developers create TypeScript models and services that reflect our backend model and REST services. It was a tedious job. What is more, after they finally mirrored what we had on the backend, it wasn't the end. Because we always have to keep in mind one thing that is very common in software development... CHANGE. Due to some new business requirements, backend services were modified. The change forced frontend developers to reanalyze backend services and refactor frontend applications so that they would match the server-side.

After some time, I have started my adventure with web development and came up with the idea that all this code could be generated based on type information in Java. I began to look for a TypeScript generator that would be able to create models and services in TypeScript base upon REST interfaces. As my research revealed, there were some libraries providing such functionality already, but none of them covered all our needs such as:

  • Support for JavaBean convention.
  • Support for FasterXML/Jackson annotation.
  • Support for Spring framework — the generation of TypeScript services that can call REST APIs developed in Spring.
  • Generated services aligned with Angular and ReactJS specific requirements (Observable or Promises API).

As a result, we decided to launch a small off-hours project that would provide the above functionality. It works, and we came up with the solution ready to use. It was tested and used in most of our commercial projects where web applications were based on Angular or React.

As our experienced showed, our library brought great benefits. The average generated code was on a level of 20% of web application codebase, but in terms of saved work on changes and tests, it was invaluable. Having such promising results, our company decided to make the project open source. If your development setup uses the Spring framework on the backend and Angular or React on the frontend side, you can experience the same benefits that we did. In this short article, I would like to introduce how you can REST with our spring-rest-2-ts TypeScript generator.

Examples

To get an idea of what spring-rest2ts generator can do, let's create a simple model and REST controller in Java, and we will show what will be generated in TypeScript

public class BaseDTO {
    private int id;
    @JsonFormat(shape = JsonFormat.Shape.NUMBER)
    private Date updateTimeStamp;
 }

public class OrderDTO extends BaseDTO {
    private double price;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    private LocalDateTime orderTimestamp;
}


Spring REST controller:

@Controller
@RequestMapping("api/order")
public class OrderCtrl {

    @PostMapping(consumes = {"application/json"}, produces = {"application/json"})
    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    public OrderDTO createOrder(@RequestBody OrderDTO entity) {
        return entity;
    }

    @RequestMapping(path = "/{id}", method = RequestMethod.GET, produces = {"application/json"})
    @ResponseBody
    public OrderDTO getOrder(@PathVariable int id) {
        return new OrderDTO();
    }

}


In TypeScript, for DTO classes, we get two interfaces with mapped inheritance, where each field is mapped to their respective TypeScript types:

export interface Base {
    id: number;
    updateTimeStamp: number;
}

export interface Order extends Base {
    price: number;
    /**
     *    pattern : dd-MM-yyyy hh:mm:ss
     */
    orderTimestamp: string;
}


As we see, if a field has Jackson annotation, it is taken into account. If not, its transformation is based on Java types to TypeScript mapping. There is support for Type names mapping. In Java, we see that there is OrderDTO by providing proper name mapper which cuts off postfix DTO and we get type Order

Observable Based Service

The mapping of model classes is quite easy to understand. What's more interesting is the mapping of Spring REST controllers for which, in TypeScript, there is a generated implementation to call endpoints. Such an approach hides under method names, paths, and parameters, so the code will be resistant to changes on the backend. What is more important is that we transform return types to selected web frameworks; for Angular 2+ there is a generated valid Angular service ready to use for injection:

@Injectable()
export class OrderService {
    httpService: HttpClient;

    public constructor(httpService: HttpClient) {
        this.httpService = httpService;
    }

    public createOrder(entity: Order): Observable<Order> {
        let headers = new HttpHeaders().set('Content-type', 'application/json');
        return this.httpService.post<Order>('api/order', entity, {headers});
    }

    public getOrder(id: number): Observable<Order> {
        return this.httpService.get<Order>('api/order/' + id + '');
    }

}


OrderService is generated for OrderCtrl. Here, the type name was also transformed by the type name mapper. If the REST API is not available on the same host as the web application, there is a possibility to configure baseURL, which could be a path prefix o entire host reference

Promise Based Service

For web frameworks that are using the Promise API generator, proper configuration is also able to generate a service class:

export class OrderService {
    baseURL: URL;


    public constructor(baseURL: URL = new URL(window.document.URL)) {
        this.baseURL = baseURL;
    }

    public createOrder(entity: Order): Promise<Order> {
        const url = new URL('/api/order', this.baseURL);

        return fetch(url.toString(), {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify(entity)
        }).then(res => res.json());
    }

    public getOrder(id: number): Promise<Order> {
        const url = new URL('/api/order/' + id + '', this.baseURL);

        return fetch(url.toString(), {method: 'GET'}).then(res => res.json());
    }

}


Configuration

Due to the greater flexibility, TypeScript generator is configured by code; no configuration files are needed. This gives a possibility to easily extend generator in places where it is needed. Here is the simplest generator configurator:

    Rest2tsGenerator tsGenerator = new Rest2tsGenerator();

    // Java Classes filtering
    tsGenerator.setModelClassesCondition(new ExtendsJavaTypeFilter(BaseDTO.class));
    tsGenerator.setRestClassesCondition(new ExtendsJavaTypeFilter(BaseCtrl.class));

    // Java model classes converter setup
    JacksonObjectMapper jacksonObjectMapper = new JacksonObjectMapper();
    jacksonObjectMapper.setFieldsVisibility(JsonAutoDetect.Visibility.ANY);
    modelClassesConverter = new ModelClassesToTsInterfacesConverter(jacksonObjectMapper);
    modelClassesConverter.setClassNameMapper(new SubstringClassNameMapper("DTO", ""));
    tsGenerator.setModelClassesConverter(modelClassesConverter);

    // Spring REST controllers converter
    restClassesConverter = new SpringRestToTsConverter(new Angular4ImplementationGenerator());
    restClassesConverter.setClassNameMapper(new SubstringClassNameMapper("Ctrl", "Service"));
    tsGenerator.setRestClassesConverter(restClassesConverter);

    // set of java root packages for class scanning
    javaPackageSet = Collections.singleton("com.blueveery.springrest2ts.examples");
    tsGenerator.generate(javaPackageSet, Paths.get("../target/ts-code"));


For more information please check the project page on Github https://github.com/blue-veery-gmbh/spring-rest-2-ts.


Further Reading

  • Foundations of RESTful Architecture.
  • All About Spring Boot [Tutorials and Articles].
REST Web Protocols Spring Framework TypeScript

Opinions expressed by DZone contributors are their own.

Related

  • Spring Boot - How To Use Native SQL Queries | Restful Web Services
  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)
  • RESTful Web Services: How To Create a Context Path for Spring Boot Application or Web Service
  • Aggregating REST APIs Calls Using Apache Camel

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!