Data Injectors
Cortex provides a number of data injectors for injecting data into prototype instances. Data injector annotations are always accompanied by an @Inject annotation. For more information and examples on when and how to use data injectors, see Resource Identifiers.
Data injectors can be put into two main categories:
- Contextual Data Injectors
- Request Data Injectors
Contextual Data Injectors
| Annotation | Description |
|---|---|
@UserCurrency | Inject the currency, Currency. |
@UserId | Inject the current User ID String. |
@UserLocale | Inject the locale Locale. |
@UserScopes | Injects all scopes if the annotated type is Iterable<String>. |
@UserSubject | Inject the scope Subject. |
Request Data Injectors
| Annotation | Description |
|---|---|
@RequestForm | Inject a ResourceEntity that encapsulates the input data. |
@RequestIdentifier | Inject a ResourceIdentifier. |
@UriPart | Inject an IdentifierPart. This reference can be typed, such as IdentifierPart<String>. |
Using @RequestForm Data Injectors
The @RequestForm data injector injects a ResourceEntity into a Prototype instance.
A ResourceEntity is a representation of the input form data submitted by the client. The @RequestForm data injector should be used in the context of a PUT or Create operation. In some cases a client may not submit any form data, thus the ResourceEntity to inject would not be present.
The default usage of the @RequestForm data injector is:
@Inject
@RequestForm
private MyResourceEntity entity
If a client tries to submit an empty form, the injection will fail and a HTTP Bad Request (status code 400) response will be returned to the client.
If you would like to define your own empty form handling behavior, inject a ResourceEntity typed Optional. In the case of an empty form the Optional would be absent.
@Inject
@RequestForm
private Optional<MyResourceEntity> maybeEntity
OSGi Service Injectors
| Annotation | Description |
|---|---|
@ResourceRepository | Inject a Repository typed to a specific ResourceEntity and ResourceIdentifier. |
@ResourceService | Inject an OSGi Service. |
Using @ResourceRepository and @ResourceService
@ResourceRepository and @ResourceService let a class in your resource bundle use a service published to the OSGi service registry by another bundle, without writing any Guice wiring for it.
Both are Guice binding annotations. @Inject marks where Guice injects a value. The annotation tells Cortex that the value comes from the OSGi service registry. When the bundle's Guice injector is created, Cortex finds every injection point that carries one of these annotations and binds its type to a provider. That provider looks up the matching OSGi service each time a value is injected, so a redeployed service is picked up without restarting the bundle.
Use @ResourceRepository for a Repository typed to a specific ResourceEntity and ResourceIdentifier:
@Inject
@ResourceRepository
private Repository<MyResourceEntity, MyResourceIdentifier> repository;
Use @ResourceService for any other OSGi service:
@Inject
@ResourceService
private MyService myService;
Both annotations work in any class that the bundle's Guice injector creates or injects, including prototypes and PermissionParameterStrategy implementations. You can also inject Provider<T> in place of T.
Cortex finds these injection points by scanning the classes in your bundle and the classes of instances your wiring binds with toInstance, such as a PermissionParameterStrategy from another bundle registered in registerParameterResolvers. Injection points declared in any other class from another bundle, such as a superclass or a class bound with bind(...).to(...), are not found.
Equivalent Guice wiring
For @ResourceService, the annotation does roughly what this binding would do if you added it to your wiring class:
@Override
protected void configurePrototypes() {
bind(MyService.class)
.annotatedWith(ResourceService.class)
.toProvider(service(MyService.class).single());
}
You don't need this binding, and you shouldn't add it: Cortex creates the binding itself, and binding the same annotated type twice fails when the injector is created.
For @ResourceRepository there is no simple equivalent. Every Repository implementation registers in the OSGi service registry under the same Repository interface, so a plain service lookup cannot tell Repository<OrderEntity, OrderIdentifier> apart from Repository<AccountEntity, AccountIdentifier>. @ResourceRepository selects the implementation whose generic type arguments match the injection point.
If the annotation is missing
Without @ResourceRepository or @ResourceService, Cortex does not create a binding for the injection point. Guice then looks for an ordinary binding of that type and, for an interface, fails with an error such as No implementation for Repository<MyResourceEntity, MyResourceIdentifier> was bound.
If the injected type is a concrete class rather than an interface, Guice does not fail. It quietly creates a new instance of that class instead of using the OSGi service, so the injected object is not the service your bundle expects. Always inject services through their interface.
Enabling Validation for Data Injectors
You can enable compile-time validation to ensure that data injections are of the correct type required. To enable validation, see Enabling Validation.