The framework provides some built-in services you can inject by type in components and actions out of the box.
Here is the list:
Type | Description | ||||
---|---|---|---|---|---|
|
Provides a small abstraction to cache data which don’t need to be recomputed very often. Commonly used by actions for the UI interactions. |
||||
|
Allows to resolve a dependency from its Maven coordinates. |
||||
|
A JSON-B instance. If your model is static and you don’t want to handle the serialization manually using JSON-P you can inject that instance. |
||||
|
A JSON-P instance. Prefer other JSON-P instances if you don’t exactly know why you use this one. |
||||
|
A JSON-P instance. It is recommended to use this one instead of a custom one for memory/speed optimizations. |
||||
|
A JSON-P instance. It is recommended to use this one instead of a custom one for memory/speed optimizations. |
||||
|
A JSON-P instance. It is recommended to use this one instead of a custom one for memory/speed optimizations. |
||||
|
A JSON-P instance. It is recommended to use this one instead of a custom one for memory/speed optimizations. |
||||
|
A JSON-P instance. It is recommended to use this one instead of a custom one for memory/speed optimizations. |
||||
|
Represents the local configuration which can be used during the design.
|
||||
Every interface that extends |
This let you define an http client in a declarative manner using an annotated interface.
|
all these injected instances are serializable which is important for the big data environment, if you create the instances yourself you will not benefit from that features and the memory optimization done by the runtime so try to prefer to reuse the framework instances over custom ones. |
HttpClient usage
Let assume that we have a REST API defined like below, and that it requires a basic authentication header.
GET |
- |
POST |
with a json playload to be created |
To create an http client able to consume this REST API, we will define an interface that extends HttpClient
,
The HttpClient
interface lets you set the base
for the http address that our client will hit.
The base
is the part of the address that we will need to add to the request path to hit the api.
Every method annotated with @Request
of our interface will define an http request.
Also every request can have @Codec
that let us encode/decode the request/response playloads.
if your payload(s) is(are) String or Void you can ignore the coder/decoder.
|
public interface APIClient extends HttpClient {
@Request(path = "api/records/{id}", method = "GET")
@Codec(decoder = RecordDecoder.class) //decoder = decode returned data to Record class
Record getRecord(@Header("Authorization") String basicAuth, @Path("id") int id);
@Request(path = "api/records", method = "POST")
@Codec(encoder = RecordEncoder.class, decoder = RecordDecoder.class) //encoder = encode record to fit request format (json in this example)
Record createRecord(@Header("Authorization") String basicAuth, Record record);
}
The interface should extends HttpClient .
|
In the codec classes (class that implement Encoder/Decoder) you can inject any of your services annotated with @Service
or @Internationalized
into the constructor.
The i18n services can be useful to have i18n messages for errors handling for example.
This interface can be injected into our Components classes or Services to consume the defined api.
@Service
public class MyService {
private APIClient client;
public MyService(...,APIClient client){
//...
this.client = client;
client.base("http://localhost:8080");// init the base of the api, ofen in a PostConstruct or init method
}
//...
// Our get request
Record rec = client.getRecord("Basic MLFKG?VKFJ", 100);
//...
// Our post request
Record newRecord = client.createRecord("Basic MLFKG?VKFJ", new Record());
}
Note: by default /+json
are mapped to JSON-P and /+xml
to JAX-B if the model has a @XmlRootElement
annotation.
Advanced HTTP client request customization
For advanced cases you can customize the Connection
directly using @UseConfigurer
on the method.
It will call your custom instance of Configurer
. Note that you can use some @ConfigurerOption
in the method
signature to pass some configurer configuration.
For instance if you have this configurer:
public class BasicConfigurer implements Configurer {
@Override
public void configure(final Connection connection, final ConfigurerConfiguration configuration) {
final String user = configuration.get("username", String.class);
final String pwd = configuration.get("password", String.class);
connection.withHeader(
"Authorization",
Base64.getEncoder().encodeToString((user + ':' + pwd).getBytes(StandardCharsets.UTF_8)));
}
}
You can then set it on a method to automatically add the basic header with this kind of API usage:
public interface APIClient extends HttpClient {
@Request(path = "...")
@UseConfigurer(BasicConfigurer.class)
Record findRecord(@ConfigurerOption("username") String user, @ConfigurerOption("password") String pwd);
}