-
Notifications
You must be signed in to change notification settings - Fork 238
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 (
AxiosClientExtension
extension) - generic client class which delegates requests to some library (
generateJaxrsApplicationClient
parameter) - or just TypeScript interface (
generateJaxrsApplicationInterface
parameter)
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:
-
singleObject
means that one object with all operations will be generated (default) -
perResource
means that for each root resource one object will be generated -
byAnnotation
means that operations will be grouped by annotating root resources with annotation specified usingjaxrsNamespacingAnnotation
parameter.
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
).