-
Notifications
You must be signed in to change notification settings - Fork 250
JAX RS Application
typescript-generator has support for JAX-RS application:
- It can discover REST resource and JSON classes used in JAX-RS REST service.
- It can generate client for JAX-RS REST service. Currently client can be:
- Axios client implementation usable out of the box (
AxiosClientExtensionextension) - generic client class which delegates requests to some library (
generateJaxrsApplicationClientparameter) - or just TypeScript interface (
generateJaxrsApplicationInterfaceparameter)
You can start with this Maven example which automatically discovers REST resources and generates Axios service client:
<configuration>
<outputFileType>implementationFile</outputFileType>
<outputKind>module</outputKind>
<classesFromAutomaticJaxrsApplication>true</classesFromAutomaticJaxrsApplication>
<extensions>
<extension>cz.habarta.typescript.generator.ext.AxiosClientExtension</extension>
</extensions>
</configuration>Below are details of 1. class discovery and 2. generated clients.
Class discovery is convenient way how to specify which classes should be processed.
For example from this REST resource class:
@Path("user")
public class UserResource {
@GET
public User getCurrentUser() {}
}typescript-generator can discover JSON class User and generate TypeScript declaration for it.
Resource classes can either be found automatically or using JAX-RS application class.
Automatic way can be turned on using classesFromAutomaticJaxrsApplication parameter.
Here is Maven configuration snippet:
<configuration>
<classesFromAutomaticJaxrsApplication>true</classesFromAutomaticJaxrsApplication>
</configuration>If automatic way doesn't work as needed you can configure specific Application class from which
typescript-generator can get list of classes.
In previous versions this could be configured using classesFromJaxrsApplication parameter
but now Application class is also used when it is reached using classes or classPatterns parameter.
Example JAX-RS application:
public class TestApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
return new LinkedHashSet<Class<?>>(Arrays.asList(
UserResource.class
));
}
}and snippet for Maven:
<configuration>
<classes>
<class>cz.habarta.TestApplication</class>
</classes>
</configuration>When application class is parsed it must have no-argument constructor which should not have any side-effects like communication with database, starting new threads etc.
If your application has constructor with parameters you can add second constructor (can be
private) or second application (possibly with inheritance).
Application class doesn't have to derive directly from javax.ws.rs.core.Application, it can derive from some framework class like org.glassfish.jersey.server.ResourceConfig in Jersey.
If there is a guice version conflict between your application and typescript-generator-maven-plugin either
- remove guice initialization from no-argument constructor or
- add following dependency to the plugin.
<plugin>
<groupId>cz.habarta.typescript-generator</groupId>
<artifactId>typescript-generator-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-guice</artifactId>
<version>3.2.6</version>
</dependency>
</dependencies>
</plugin>This feature provides convenient way how to use REST service from TypeScript. Typescript-generator generates client class with methods that has typed parameters and return types and make HTTP requests to particular URL path.
Client class for JAX-RS service can be generated using generateJaxrsApplicationClient configuration parameter.
Let's see example. For this resource:
@Path("people/{personId}")
private static class PersonResource {
@PathParam("personId")
protected long personId;
@GET
public Person getPerson() {
return null;
}
@GET
@Path("address/{addressId}")
public Address getAddress(@PathParam("addressId") long addressId) {
return null;
}
}following client class will be generated:
class RestApplicationClient {
constructor(private httpClient: HttpClient) {
}
getPerson(personId: number): RestResponse<Person> {
return this.httpClient.request({ method: "GET", url: `api/people/${personId}` });
}
getAddress(personId: number, addressId: number): RestResponse<Address> {
return this.httpClient.request({ method: "GET", url: `api/people/${personId}/address/${addressId}` });
}
}Here is Maven example how to use this functionality:
<configuration>
<outputFileType>implementationFile</outputFileType>
<outputKind>module</outputKind>
<classesFromAutomaticJaxrsApplication>true</classesFromAutomaticJaxrsApplication>
<generateJaxrsApplicationClient>true</generateJaxrsApplicationClient>
</configuration>Generated client class delegates requests to some HttpClient adapter
which is set in constructor and can be implemented using arbitrary HTTP API or library like XMLHttpRequest, jQuery, axios, Angular etc.
This is HttpClient interface definition:
interface HttpClient {
request(requestConfig: { method: string; url: string; queryParams?: any; data?: any; }): RestResponse<any>;
}This interface can be implemented in typescript-generator extension (like cz.habarta.typescript.generator.ext.AxiosClientExtension) or in user code.
Note that you can create multiple instances of client class. This can be useful for example for tests running in Node.js where each client can have different logged-in user cookie or header.
Methods have RestResponse return type which is by default defined as:
type RestResponse<R> = Promise<R>;This definition can be configured using restResponseType parameter.
Using restOptionsType parameter it is possible to pass additional options to request methods.
Customization parameters can be combined with importDeclarations or referencedFiles parameter to use types from some library.
Here is Maven example with customization for axios library:
<configuration>
<outputFileType>implementationFile</outputFileType>
<outputKind>module</outputKind>
<classesFromAutomaticJaxrsApplication>true</classesFromAutomaticJaxrsApplication>
<generateJaxrsApplicationClient>true</generateJaxrsApplicationClient>
<importDeclarations>
<import>import axios from "axios"</import>
<import>import { AxiosRequestConfig, AxiosPromise } from "axios"</import>
</importDeclarations>
<restOptionsType>AxiosRequestConfig</restOptionsType>
<restResponseType>AxiosPromise</restResponseType>
</configuration>By default single client class with all REST operations is generated. This is convenient but often results in many name conflicts. So it is possible to organize operations using jaxrsNamespacing parameter. Options are:
-
singleObjectmeans that one object with all operations will be generated (default) -
perResourcemeans that for each root resource one object will be generated -
byAnnotationmeans that operations will be grouped by annotating root resources with annotation specified usingjaxrsNamespacingAnnotationparameter.
Format of jaxrsNamespacingAnnotation parameter is <annotationClass>#<annotationElement> - for example io.swagger.annotations.Api#value. <annotationElement> can be omitted and defaults to value - for example io.swagger.annotations.Api.
Instead of (or in addition to) client class it is also possible to generate TypeScript interface for JAX-RS application.
This can be turned on using generateJaxrsApplicationInterface configuration parameter.
While client implementation can only be generated in implementation file (.ts)
interface can be generated also in declaration file (.d.ts).